Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2019 Yak.Works - Licensed under the Apache License, Version 2.0 (the "License")
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
package gorm.tools.mango
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.codehaus.groovy.runtime.InvokerHelper
import org.grails.datastore.mapping.model.PersistentProperty
import org.grails.datastore.mapping.model.types.Association
import org.grails.datastore.mapping.query.Query
import org.grails.datastore.mapping.query.api.QueryableCriteria
import org.springframework.beans.factory.annotation.Autowired
import gorm.tools.databinding.EntityMapBinder
import gorm.tools.mango.api.QueryArgs
import grails.gorm.DetachedCriteria
import yakworks.commons.lang.ClassUtils
import yakworks.commons.lang.EnumUtils
import yakworks.commons.model.IdEnum
import static gorm.tools.mango.MangoOps.CompareOp
import static gorm.tools.mango.MangoOps.ExistOp
import static gorm.tools.mango.MangoOps.JunctionOp
import static gorm.tools.mango.MangoOps.OverrideOp
import static gorm.tools.mango.MangoOps.PropertyOp
import static gorm.tools.mango.MangoOps.QSEARCH
import static gorm.tools.mango.MangoOps.SORT
import static gorm.tools.mango.MangoOps.SubQueryOp
/**
* the main builder to turn Mango QL Maps or json into DetachedCriteria for Gorm
*
* @author Joshua Burnett (@basejump)
* @since 6.1
*/
@SuppressWarnings(['FieldName', 'ConfusingMethodName']) //codenarc doesn't like the names we use to make this builder clean
@CompileStatic
@Slf4j
class MangoBuilder {
@Autowired QuickSearchSupport quickSearchSupport
@CompileDynamic //dynamic so it can access the protected criteria.clone
static MangoDetachedCriteria cloneCriteria(DetachedCriteria criteria) {
(MangoDetachedCriteria)criteria.clone()
}
public MangoDetachedCriteria build(Class clazz, QueryArgs qargs, @DelegatesTo(MangoDetachedCriteria) Closure callable = null) {
MangoDetachedCriteria mangoCriteria = createCriteria(clazz, qargs, callable)
applyCriteria(mangoCriteria)
return mangoCriteria
}
/**
* Creates the MangoDetachedCriteria object with the queryArgs.
* Does NOT apply or set it up yet.
*/
MangoDetachedCriteria createCriteria(Class clazz, QueryArgs queryArgs, Closure applyClosure){
MangoDetachedCriteria mangoCriteria = new MangoDetachedCriteria(clazz)
//assign the queryArgs for use later if needed
mangoCriteria.queryArgs = queryArgs
//assign the the criteriaMap and run the tidy on it to normalize it.
Map criteria = queryArgs.buildCriteriaMap()
//normalize the map and assign it
mangoCriteria.criteriaMap = MangoTidyMap.tidy(criteria)
mangoCriteria.criteriaClosure = applyClosure
return mangoCriteria
}
/**
* Applies the criteriaMap and criteriaClosure to setup the MangoDetachedCriteria
*/
MangoDetachedCriteria applyCriteria(MangoDetachedCriteria mangoCriteria){
QueryArgs qargs = mangoCriteria.queryArgs
//will be copy if sort exists
Map criteriaMap = mangoCriteria.criteriaMap
Closure applyClosure = mangoCriteria.criteriaClosure
//apply the map
applyMapOrList(mangoCriteria, criteriaMap)
//apply the closure
if (applyClosure) {
final Closure clonedClosure = (Closure) applyClosure.clone()
clonedClosure.setResolveStrategy(Closure.DELEGATE_FIRST)
mangoCriteria.with(clonedClosure)
}
//do the queryArgs but only if $sort not in criteria map
if(qargs.sort && !criteriaMap.containsKey(SORT)){
order(mangoCriteria, qargs.sort)
}
if(qargs.projections){
applyProjections(mangoCriteria, qargs.projections)
}
//apply select properties, this should not
if(qargs.select){
applySelect(mangoCriteria, qargs.select)
}
if(qargs.timeout) mangoCriteria.setTimeout(qargs.timeout)
return mangoCriteria
}
/**
* calls list for the criteria, if criteria has projections then calls mapList
* which uses JpqlQueryBuilder
*/
static List list(MangoDetachedCriteria criteria, Map args) {
List resList
if(criteria.projections){
resList = criteria.mapList(args)
} else {
//return standard list
resList = criteria.list(args)
}
return resList
}
/**
* Apply projections from map in form [key:type] where type is sum, group, count, min, max or avg
*
* @param criteria the criteria to apply the project
* @param projs the map of projections to apply
*/
void applyProjections(MangoDetachedCriteria criteria, Map projs) {
//assume its a map
(projs as Map).each { String k, String v ->
if(v == 'sum'){
criteria.sum(k)
} else if (v == 'group'){
criteria.groupBy(k)
} else if (v == 'avg'){
criteria.avg(k)
} else if (v == 'count'){
criteria.countDistinct(k)
} else if (v == 'min'){
criteria.min(k)
} else if (v == 'max'){
criteria.max(k)
}
}
}
/**
* list of properties that will go in the select clause
*/
void applySelect(MangoDetachedCriteria criteria, List projs) {
for(String prop : projs){
criteria.property(prop)
}
}
void applyMapOrList(DetachedCriteria criteria, Object mapOrList) {
if (mapOrList instanceof Map) {
applyMap(criteria, mapOrList)
} else if (mapOrList instanceof List