None Found
"); + } + + break; + } + // one to many display + case "one-to-one" : { + loc.orm = ORMGetSession(); + // A new or persisted entity? If new, then skip out + if( NOT loc.orm.contains(arguments.entity) OR NOT arguments.showRelations){ + break; + } + + arguments["data-ormtype"] = "one-to-one"; + // We just show them as a nice table because we are not scaffolding, just display + // values should be an array of objects, so let's convert them + loc.data = evaluate("arguments.entity.get#prop.name#()"); + if( isNull(loc.data) ){ loc.relArray = []; } + else{ loc.relArray = [ loc.data ]; } + + // Label Generation + args = { + field=prop.name, wrapper=arguments.labelWrapper, class=arguments.labelClass + }; + structAppend(args,arguments); + buffer.append( this.label(argumentCollection=args) ); + + // Table Generation + if( arrayLen(loc.relArray) ){ + args = { + name=prop.name, data=loc.relArray + }; + structAppend(args,arguments); + buffer.append( this.table(argumentCollection=args) ); + } + else{ + buffer.append("None Found
"); + } + break; + } + // many to one + case "many-to-one" : { + arguments["data-ormtype"] = "many-to-one"; + // prepare lookup args + loc.criteria = {}; + loc.sortorder = ""; + loc.column = ""; + loc.nameColumn = ""; + // is key found in manytoone arg + if( structKeyExists(arguments.manytoone, prop.name) ){ + // Verify the valueColumn which is mandatory + if( structKeyExists(arguments.manytoone[prop.name],"valueColumn") ){ loc.column = arguments.manytoone[prop.name].valueColumn; } + else{ + throw(message="The 'valueColumn' property is missing from the '#prop.name#' relationship data, which is mandatory", + detail="A structure of data to help with many to one relationships on how they are presented. Possible key values for each key are [valuecolumn='',namecolumn='',criteria={},sortorder=string]. Example: {criteria={productid=1},sortorder='Department desc'}", + type="EntityFieldsInvalidRelationData"); + } + if( structKeyExists(arguments.manytoone[prop.name],"nameColumn") ){ loc.nameColumn = arguments.manytoone[prop.name].nameColumn; } + else { loc.nameColumn = arguments.manytoone[prop.name].valueColumn; } + if( structKeyExists(arguments.manytoone[prop.name],"criteria") ){ loc.criteria = arguments.manytoone[prop.name].criteria; } + if( structKeyExists(arguments.manytoone[prop.name],"sortorder") ){ loc.sortorder = arguments.manytoone[prop.name].sortorder; } + } + else{ + throw(message="There is no many to one information for the '#prop.name#' relationship in the entityFields() arguments. Please make sure you create one", + detail="A structure of data to help with many to one relationships on how they are presented. Possible key values for each key are [valuecolumn='',namecolumn='',criteria={},sortorder=string]. Example: {criteria={productid=1},sortorder='Department desc'}", + type="EntityFieldsInvalidRelationData"); + } + // generation args + args = { + name=prop.name, options=entityLoad( prop.cfc, loc.criteria, loc.sortorder ), + column=loc.column, nameColumn=loc.nameColumn, + label=prop.name, bind=arguments.entity, labelwrapper=arguments.labelWrapper, labelClass=arguments.labelClass, + wrapper=arguments.fieldwrapper, groupWrapper=arguments.groupWrapper + }; + structAppend(args,arguments); + buffer.append( this.select(argumentCollection=args) ); + break; + } + // columns + case "column" : { + + // booleans? + if( structKeyExists(prop,"ormtype") and prop.ormtype eq "boolean"){ + // boolean select or radio buttons + if( arguments.booleanSelect ){ + args = { + name=prop.name, options=[true,false], label=prop.name, bind=arguments.entity, labelwrapper=arguments.labelWrapper, labelClass=arguments.labelClass, + wrapper=arguments.fieldwrapper, groupWrapper=arguments.groupWrapper + }; + structAppend(args,arguments); + buffer.append( this.select(argumentCollection=args) ); + } + else{ + args = { + name=prop.name, value="true", label="True", bind=arguments.entity, labelwrapper=arguments.labelWrapper, labelClass=arguments.labelClass, + groupWrapper=arguments.groupWrapper, wrapper=arguments.fieldWrapper + }; + structAppend(args,arguments); + buffer.append( this.radioButton(argumentCollection=args) ); + args.value="false"; + args.label="false"; + buffer.append( this.radioButton(argumentCollection=args) ); + } + continue; + } + // text args + args = { + name=prop.name, label=prop.name, bind=arguments.entity, labelwrapper=arguments.labelWrapper, labelClass=arguments.labelClass, + wrapper=arguments.fieldwrapper, groupWrapper=arguments.groupWrapper + }; + structAppend(args,arguments); + // text and textarea fields + if( len(arguments.textareas) AND listFindNoCase(arguments.textareas, prop.name) ){ + buffer.append( this.textarea(argumentCollection=args) ); + } + else{ + buffer.append( this.textfield(argumentCollection=args) ); + } + }// end case column + + }// end switch + + }// end for loop + + return buffer.toString(); +tags for more readable output - * return CriteriaBuilder - */ - public any function startSqlLog( required Any returnExecutableSql=false, required Any formatSql=false ) { - SQLHelper.setReturnExecutableSql( arguments.returnExecutableSql ); - SQLHelper.setFormatSql( arguments.formatSql ); - sqlLoggerActive = true; - return this; - } - - /** - * Stops CriteriaBuilder from continuing to internally log the state of SQL - * return CriteriaBuilder - */ - public any function stopSqlLog() { - sqlLoggerActive = false; - return this; - } - - /** - * Allows for one-off sql logging at any point in the process of building up CriteriaBuilder; will log the SQL state at the time of the call - * @label {String} The label to use for the sql log record - * return void - */ - public void function logSQL( required String label ) { - SQLHelper.log( argumentCollection=arguments ); - } - - /** - * Returns whether or not CriteriaBuilder is currently configured to log SQL - * return Boolean - */ - public boolean function canLogSql() { - return sqlLoggerActive; - } - /************************************** PRIVATE *********************************************/ - - /** - * Checks whether or not a projection is currently applied to the CriteriaBuilder - * return Boolean - */ - private boolean function hasProjection() { - var projectionExists = false; - if( !isNull( nativeCriteria.getProjection() ) ) { - projectionExists = nativeCriteria.getProjection().getLength() ? true : false; - } - return projectionExists; - } - - // Simplified additions of projections - private function addProjection(any propertyName,any projectionType,any projectionList){ - // inflate to array - if( isSimpleValue(arguments.propertyName) ){ arguments.propertyName = listToArray(arguments.propertyName); } - // iterate array and add projections - for(var thisP in arguments.propertyName){ - // add projection - arguments.projectionList.add( evaluate("this.PROJECTIONS.#arguments.projectionType#( listFirst(thisP,':') )"), listLast(thisP,":") ); - - // announce - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Projection", - "criteriaBuilder" = this - }); - } - - } - } - - /** - * Helper method to prepare sqlProjection for addition to CriteriaBuilder - * @rawProjection {Struct} The raw projection configuration - * return Struct - */ - private struct function prepareSQLProjection( rawProjection ) { - // get metadata for current root entity - var metaData = ORMService.getORM().getSessionFactory( ORMService.getORM().getEntityDatasource( this.getentityName() ) ) - .getClassMetaData( this.getentityName() ); - // establish projection struct - var projection = {}; - // create empty array for propertyTypes - var projection.types = []; - // retrieve correct type for each specified property so list() doesn't bork - for( var prop in listToArray( arguments.rawProjection.property ) ) { - arrayAppend( projection.types, metaData.getPropertyType( prop ) ); - } - var partialSQL = ""; - projection.sql = ""; - // if multiple subqueries have been specified, smartly separate them out into a sql string that will work - for( var x=1; x<=listLen( arguments.rawProjection.sql ); x++ ) { - partialSQL = listGetAt( arguments.rawProjection.sql, x ); - partialSQL = reFindNoCase( "^select", partialSQL ) ? "(#partialSQL#)" : partialSQL; - partialSQL = partialSQL & " as #listGetAt( arguments.rawProjection.alias, x )#"; - projection.sql = listAppend( projection.sql, partialSQL ); - } - // get all aliases - projection.alias = listToArray( arguments.rawProjection.alias ); - // if there is a grouping spcified, add it to structure - if( structKeyExists( arguments.rawProjection, "group" ) ) { - projection.group = arguments.rawProjection.group; - } - return projection; - } - - // Normalize Sort orders - private void function normalizeOrder(required string sortOrder,required boolean ignoreCase){ - - var sortLen = listLen(arguments.sortOrder); - - for(var x=1; x lte sortLen; x++){ - var thisSort = listGetAt(arguments.sortOrder,x); - var sortField = Trim(ListFirst(thisSort," ")); - var sortDir = "ASC"; - if(ListLen(thisSort," ") GTE 2){ - sortDir = ListGetAt(thisSort,2," "); - } - // add it to our ordering - order(sortField,sortDir,arguments.ignoreCase); - } - } - - // creates either a new criteria query, or a new restriction, and returns the result - private any function createRestriction( required string missingMethodName, required struct missingMethodArguments ){ - // check for with{association} dynamic finder: - if( left(arguments.missingMethodName,4) eq "with" ){ - var args = { - associationName = right( arguments.missingMethodName, len(arguments.missingMethodName)-4) - }; - // join type - if( structKeyExists(arguments.missingMethodArguments,"1") ){ - args.joinType = arguments.missingMethodArguments[1]; - } - if( structKeyExists(arguments.missingMethodArguments,"joinType") ){ - args.joinType = arguments.missingMethodArguments.joinType; - } - // create the dynamic criteria - return createCriteria(argumentCollection=args); - } - //arguments.missingMethodArguments.nativeCriteria = getNativeCriteria(); - // funnel missing methods to restrictions and append to criterias - var r = evaluate("this.restrictions.#arguments.missingMethodName#(argumentCollection=arguments.missingMethodArguments)"); - return r; - } -} diff --git a/src/cfml/system/wirebox/system/orm/hibernate/BaseORMService.cfc b/src/cfml/system/wirebox/system/orm/hibernate/BaseORMService.cfc deleted file mode 100644 index 6c054ec13..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/BaseORMService.cfc +++ /dev/null @@ -1,1493 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Luis Majano -Description : - -This is a helper ORM service that will help you abstract some complexities -when dealing with CF's ORM via Hibernate. You can use this service in its -concrete form or you can inherit from it and extend it. - -TODO: -- Add dynamic findBy methods -- Add dynamic countBy methods -- Add dynamic getBy methods -- Dynamic entity methods for the following methods: - - new{entityName}() - - exists{entityName}() - - get{entityName}() - - getAll{entityName}() - - count{entityName}() -- Add find methods by criteria with projections ------------------------------------------------------------------------> -*/ -import wirebox.system.orm.hibernate.util.*; - -component accessors="true"{ - - /** - * The queryCacheRegion name property for all query caching produced in this service - */ - property name="queryCacheRegion" type="string" default="ORMService.defaultCache"; - - /** - * The bit that tells the service to enable query caching, disabled by default - */ - property name="useQueryCaching" type="boolean" default="false"; - - /** - * The bit that enables event handling via the ORM Event handler such as interceptions when new entities get created, etc, enabled by default. - */ - property name="eventHandling" type="boolean" default="true"; - - /** - * The system ORM event handler to transmitt ORM events to - */ - property name="ORMEventHandler"; - - /** - * The system ORM utility object - */ - property name="ORM"; - - /** - * The bit that enables automatic hibernate transactions on all save, saveAll, update, delete methods - */ - property name="useTransactions" type="boolean" default="true"; - - /** - * The bit that determines the default return value for list(), createCriteriaQuery() and executeQuery() as query or array - */ - property name="defaultAsQuery" type="boolean" default="true"; - - /** - * All calculated and parsed dynamic finders' and counters' HQL will be stored here for easier execution - */ - property name="HQLDynamicCache" type="struct"; - - // STATIC DYNAMIC FINDER VARIABLES - ALL_CONDITIONALS = "LessThanEquals,LessThan,GreaterThanEquals,GreaterThan,Like,NotEqual,isNull,isNotNull,NotBetween,Between,NotInList,inList"; - ALL_CONDITIONALS_REGEX = replace( ALL_CONDITIONALS, ",", "|", "all" ); - CONDITIONALS_SQL_MAP = { - "LessThanEquals" = "<=", - "LessThan" = "<", - "GreaterThanEquals" = ">=", - "GreaterThan" = ">", - "Like" = "like", - "NotEqual" = "<>", - "isNull" = "is null", - "isNotNull" = "is not null", - "NotBetween" = "not between", - "between" = "between", - "NotInList" = "not in", - "InList" = "in" }; - - /************************************** CONSTRUCTOR *********************************************/ - - BaseORMService function init( - string queryCacheRegion="ORMService.defaultCache", - boolean useQueryCaching=false, - boolean eventHandling=true, - boolean useTransactions=true, - boolean defaultAsQuery=true - ){ - - // setup local properties - variables.queryCacheRegion = arguments.queryCacheRegion; - variables.useQueryCaching = arguments.useQueryCaching; - variables.eventHandling = arguments.eventHandling; - variables.useTransactions = arguments.useTransactions; - variables.defaultAsQuery = arguments.defaultAsQuery; - variables.HQLDynamicCache = {}; - - // Create the ORM Utility component - variables.ORM = new wirebox.system.orm.hibernate.util.ORMUtilFactory().getORMUtil(); - - // Create the service ORM Event Handler - if( directoryExists( expandPath("/wirebox") ) OR structKeyExists( application, "cblite" ) ){ - variables.ORMEventHandler = new wirebox.system.orm.hibernate.WBEventHandler(); - } - else{ - variables.ORMEventHandler = new wirebox.system.orm.hibernate.EventHandler(); - } - - // Create our bean populator utility object - variables.beanPopulator = new wirebox.system.core.dynamic.BeanPopulator(); - // Restrictions orm.hibernate.criterion.Restrictions - variables.restrictions = new wirebox.system.orm.hibernate.criterion.Restrictions(); - - return this; - } - - /************************************** PUBLIC *********************************************/ - - /** - * Create a virtual abstract service for a specfic entity. - */ - any function createService(required string entityName, - boolean useQueryCaching=getUseQueryCaching(), - string queryCacheRegion=getQueryCacheRegion(), - boolean eventHandling=getEventHandling()) { - - return new wirebox.system.orm.hibernate.VirtualEntityService( argumentCollection=arguments ); - } - - /** - * List all of the instances of the passed in entity class name. You can pass in several optional arguments like - * a struct of filtering criteria, a sortOrder string, offset, max, ignorecase, and timeout. - * Caching for the list is based on the useQueryCaching class property and the cachename property is based on - * the queryCacheRegion class property. - */ - any function list(required string entityName, - struct criteria=structnew(), - string sortOrder="", - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignoreCase=false, - boolean asQuery=getDefaultAsQuery()){ - var options = {}; - - // Setup listing options - if( arguments.offset neq 0 ){ - options.offset = arguments.offset; - } - if( arguments.max neq 0 ){ - options.maxresults = arguments.max; - } - if( arguments.timeout neq 0 ){ - options.timeout = arguments.timeout; - } - - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - - // Sort Order Case - if( len(trim(arguments.sortOrder)) ){ - options.ignoreCase = arguments.ignoreCase; - } - - // Get listing - var results = entityLoad(arguments.entityName, arguments.criteria, arguments.sortOrder, options); - - // Is it Null? - if( isNull(results) ){ results = []; } - - // Objects or Query? - if( arguments.asQuery ){ - results = entityToQuery(results); - } - - return results; - } - - /** - * Allows the execution of HQL queries using several nice arguments and returns either an array of entities or a query as specified by the asQuery argument. - * The params filtering can be using named or positional. - */ - any function executeQuery(required string query, - any params=structnew(), - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignorecase=false, - boolean asQuery=getDefaultAsQuery(), - boolean unique=false, - string datasource=""){ - var options = {}; - - // Setup listing options - if( arguments.offset neq 0 ){ - options.offset = arguments.offset; - } - if( arguments.max neq 0 ){ - options.maxresults = arguments.max; - } - if( arguments.timeout neq 0 ){ - options.timeout = arguments.timeout; - } - if( Len(arguments.datasource) ){ - options.datasource = arguments.datasource; - } - options.ignorecase = arguments.ignorecase; - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - - // Get listing - var results = ORMExecuteQuery( arguments.query, arguments.params, arguments.unique, options ); - - // Null Checks - if( isNull(results) ){ - if( arguments.asQuery ){ return queryNew(""); } - if (arguments.unique) { - return; - } else { - return []; - } - } - - // Objects or Query? - if( arguments.asQuery ){ - results = entityToQuery(results); - } - - return results; - } - - /** - * Finds and returns the first result for the given query or null if no entity was found. - * You can either use the query and params combination or send in an example entity to find. - * @example.hint DEPRECATED. Use findByExample() instead, deprecated by 3.5 - */ - any function findIt(string query,any params=structnew(), any example){ - var options = {maxresults=1}; - - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - - // Get entry by example - if( structKeyExists( arguments, "example") ){ - return findByExample( arguments.example, true ); - } - - // Normal Find - return ORMExecuteQuery( arguments.query, arguments.params, true, options); - } - - /** - * Find all/single entities by example - */ - any function findByExample(any example,boolean unique=false){ - return entityLoadByExample(arguments.example,arguments.unique); - } - - /** - * Find all the entities for the specified query and params or example - * @example.hint DEPRECATED use findByExample() this will be dropped in 3.5 - */ - array function findAll(string query, - any params=structnew(), - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignoreCase=false, - any example){ - - // Get entry by example - if( structKeyExists( arguments, "example") ){ - return findByExample( arguments.example ); - } - - // Normal Execute Query - arguments.asQuery=false; - return executeQuery( argumentCollection=arguments ); - } - - /** - * Find one entity (or null if not found) according to a criteria structure - */ - any function findWhere(required string entityName, required struct criteria){ - // Caching? - if( getUseQueryCaching() ){ - //if we are caching, we will use find all and return an array since entityLoad does not support both unique and caching - var arEntity = findAllWhere( argumentCollection=arguments ); - //if we found an entity, return it - if (arrayLen(arEntity)) { - return arEntity[1]; - //else return NULL, just like entityLoad with unique would - } else { - return javaCast("null",0); - } - } else { - return entityLoad( arguments.entityName, arguments.criteria, true ); - } - } - - /** - * Find all entities according to criteria structure - */ - array function findAllWhere(required string entityName, required struct criteria, string sortOrder=""){ - var options = {}; - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - return entityLoad( arguments.entityName, arguments.criteria, arguments.sortOrder, options); - } - - /** - * Get a new entity object by entity name and you can pass in the properties structre also to bind the entity with properties - * @entityName.hint The entity to create - * @properties.hint The structure of data to populate the entity with. By default we will inspect for many-to-one, one-to-many and many-to-many relationships and compose them for you. - * @composeRelationships.hint Automatically attempt to compose relationships from the incoming properties memento - * @nullEmptyInclude.hint A list of keys to NULL when empty - * @nullEmptyExclude.hint A list of keys to NOT NULL when empty - * @ignoreEmpty.hint Ignore empty values on populations, great for ORM population - * @include.hint A list of keys to include in the population from the incoming properties memento - * @exclude.hint A list of keys to exclude in the population from the incoming properties memento - */ - any function new(required string entityName, struct properties=structnew(), boolean composeRelationships=true, nullEmptyInclude="", nullEmptyExclude="", boolean ignoreEmpty=false, include="", exclude=""){ - var entity = entityNew( arguments.entityName ); - - // Properties exists? - if( NOT structIsEmpty(arguments.properties) ){ - populate(target=entity, memento=arguments.properties, composeRelationships=arguments.composeRelationships, - nullEmptyInclude=arguments.nullEmptyInclude, nullEmptyExclude=arguments.nullEmptyExclude, ignoreEmpty=arguments.ignoreEmpty, - include=arguments.include, exclude=arguments.exclude ); - } - - // Event Handling? If enabled, call the postNew() interception - if( getEventHandling() ){ - ORMEventHandler.postNew( entity, arguments.entityName ); - } - - return entity; - } - - /** - * Simple map to property population for entities - * @memento.hint The map/struct to populate the entity with - * @scope.hint Use scope injection instead of setter injection, no need of setters, just tell us what scope to inject to - * @trustedSetter.hint Do not check if the setter exists, just call it, great for usage with onMissingMethod() and virtual properties - * @include.hint A list of keys to include in the population ONLY - * @exclude.hint A list of keys to exclude from the population - */ - any function populate(required any target, - required struct memento, - string scope="", - boolean trustedSetter=false, - string include="", - string exclude="", - boolean ignoreEmpty=false, - string nullEmptyInclude="", - string nullEmptyExclude="", - boolean composeRelationships=true){ - - return beanPopulator.populateFromStruct( argumentCollection=arguments ); - } - - /** - * Simple map to property population for entities with structure key prefixes - * @memento.hint The map/struct to populate the entity with - * @scope.hint Use scope injection instead of setter injection, no need of setters, just tell us what scope to inject to - * @trustedSetter.hint Do not check if the setter exists, just call it, great for usage with onMissingMethod() and virtual properties - * @include.hint A list of keys to include in the population ONLY - * @exclude.hint A list of keys to exclude from the population - * @prefix.hint The prefix used to filter, Example: 'user' would apply to the following formfield: 'user_id' and 'user_name' but not 'address_id' - */ - any function populateWithPrefix(required any target, - required struct memento, - string scope="", - boolean trustedSetter=false, - string include="", - string exclude="", - boolean ignoreEmpty=false, - string nullEmptyInclude="", - string nullEmptyExclude="", - boolean composeRelationships=true, - required string prefix){ - return beanPopulator.populateFromStructWithPrefix( argumentCollection=arguments ); - } - - /** - * Populate from JSON, for argument definitions look at the populate method - * @JSONString.hint The JSON packet to use for population - * @scope.hint Use scope injection instead of setter injection, no need of setters, just tell us what scope to inject to - * @trustedSetter.hint Do not check if the setter exists, just call it, great for usage with onMissingMethod() and virtual properties - * @include.hint A list of keys to include in the population ONLY - * @exclude.hint A list of keys to exclude from the population - */ - any function populateFromJSON(required any target, - required string JSONString, - string scope="", - boolean trustedSetter=false, - string include="", - string exclude="", - boolean ignoreEmpty=false, - string nullEmptyInclude="", - string nullEmptyExclude="", - boolean composeRelationships=true){ - - return beanPopulator.populateFromJSON( argumentCollection=arguments ); - } - - /** - * Populate from XML, for argument definitions look at the populate method - * @root.hint The XML root element to start from - * @xml.hint The XML string or packet or XML object to populate from - * @scope.hint Use scope injection instead of setter injection, no need of setters, just tell us what scope to inject to - * @trustedSetter.hint Do not check if the setter exists, just call it, great for usage with onMissingMethod() and virtual properties - * @include.hint A list of keys to include in the population ONLY - * @exclude.hint A list of keys to exclude from the population - */ - any function populateFromXML(required any target, - required string xml, - string root="", - string scope="", - boolean trustedSetter=false, - string include="", - string exclude="", - boolean ignoreEmpty=false, - string nullEmptyInclude="", - string nullEmptyExclude="", - boolean composeRelationships=true){ - - return beanPopulator.populateFromXML( argumentCollection=arguments ); - } - - /** - * Populate from Query, for argument definitions look at the populate method - * @qry.hint The query to use for population - * @rowNumber.hint The row number to use for population - * @scope.hint Use scope injection instead of setter injection, no need of setters, just tell us what scope to inject to - * @trustedSetter.hint Do not check if the setter exists, just call it, great for usage with onMissingMethod() and virtual properties - * @include.hint A list of keys to include in the population ONLY - * @exclude.hint A list of keys to exclude from the population - */ - any function populateFromQuery(required any target, - required any qry, - numeric rowNumber=1, - string scope="", - boolean trustedSetter=false, - string include="", - string exclude="", - boolean ignoreEmpty=false, - string nullEmptyInclude="", - string nullEmptyExclude="", - boolean composeRelationships=true){ - - return beanPopulator.populateFromQuery( argumentCollection=arguments ); - } - - - /** - * Refresh the state of an entity or array of entities from the database - */ - any function refresh(required any entity){ - var objects = arrayNew(1); - - if( not isArray(arguments.entity) ){ - arrayAppend(objects, arguments.entity); - } - else{ - objects = arguments.entity; - } - - for( var x=1; x lte arrayLen(objects); x++){ - orm.getSession(orm.getEntityDatasource(objects[x])).refresh( objects[x] ); - } - return this; - } - - /** - * Checks if the given entityName and id exists in the database, this method does not load the entity into session - */ - boolean function exists(required entityName, required any id) { - var options = {}; - options.datasource = orm.getEntityDatasource(arguments.entityName); - - // Do it DLM style - var count = ORMExecuteQuery("select count(id) from #arguments.entityName# where id = ?",[arguments.id],true,options); - return (count gt 0); - } - - /** - * Get an entity using a primary key, if the id is not found this method returns null, if the id=0 or blank it returns a new entity. - * @entityName the name of the entity to retrieve - * @id An optional primary key to use to retrieve the entity, if the id is 0 or empty - */ - any function get(required string entityName,required any id,boolean returnNew=true) { - - // check if id exists so entityLoad does not throw error - if( (isSimpleValue(arguments.id) and len(arguments.id)) OR NOT isSimpleValue(arguments.id) ){ - var entity = entityLoadByPK(arguments.entityName, arguments.id); - // Check if not null, then return it - if( NOT isNull(entity) ){ - return entity; - } - } - - // Check for return new? - if( arguments.returnNew ){ - - // Check if ID=0 or empty to do convenience new entity - if( isSimpleValue(arguments.id) and ( arguments.id eq 0 OR len(arguments.id) eq 0 ) ){ - return new(entityName=arguments.entityName); - } - - } - } - - /** - * Retrieve all the instances from the passed in entity name using the id argument if specified - * The id can be a list of IDs or an array of IDs or none to retrieve all. - */ - array function getAll(required string entityName,any id,string sortOrder="") { - var results = []; - - // Return all entity values - if( NOT structKeyExists(arguments,"id") ){ - return entityLoad(arguments.entityName,{},arguments.sortOrder); - } - - // type safe conversions - arguments.id = convertIDValueToJavaType(entityName=arguments.entityName, id=arguments.id); - var q = "FROM #arguments.entityName# where id in (:idlist)"; - // ordering? - if( len(arguments.sortOrder) ){ - q &= " ORDER BY #arguments.sortOrder#"; - } - // Execute native hibernate query - var query = orm.getSession(orm.getEntityDatasource(arguments.entityName)).createQuery(q); - // parameter binding - query.setParameterList("idlist",arguments.id); - // Caching? - if( getUseQueryCaching() ){ - query.setCacheRegion(getQueryCacheRegion()); - query.setCacheable(true); - } - return query.list(); - } - - /** - * Delete an entity. The entity argument can be a single entity - * or an array of entities. You can optionally flush the session also after committing - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - any function delete(required any entity,boolean flush=false,boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$delete, arguments); - } - $delete( argumentCollection=arguments ); - return this; - } - private any function $delete(required any entity,boolean flush=false){ - var objects = arrayNew(1); - var objLen = 0; - - if( not isArray(arguments.entity) ){ - arrayAppend(objects, arguments.entity); - } - else{ - objects = arguments.entity; - } - - objLen = arrayLen(objects); - for(var x=1; x lte objLen; x++){ - // Delete? - entityDelete( objects[x] ); - // Flush? - if( arguments.flush ){ orm.flush( orm.getEntityDatasource( objects[x] ) ); } - } - - return this; - } - - /** - * Delete all entries for an entity DLM style and transaction safe. It also returns all the count of deletions - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - numeric function deleteAll(required string entityName,boolean flush=false,boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$deleteAll, arguments); - } - return $deleteAll( argumentCollection=arguments ); - } - private numeric function $deleteAll(required string entityName,boolean flush=false){ - var options = {}; - options.datasource = orm.getEntityDatasource(arguments.entityName); - - var count = 0; - count = ORMExecuteQuery("delete from #arguments.entityName#",false,options); - - // Auto Flush - if( arguments.flush ){ orm.flush(options.datasource); } - - return count; - } - - /** - * Delete using an entity name and an incoming id, you can also flush the session if needed. The id parameter can be a single id or an array of IDs to delete - * The method returns the count of deleted entities. - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - numeric function deleteByID(required string entityName, required any id, boolean flush=false, boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$deleteByID, arguments); - } - return $deleteByID( argumentCollection=arguments ); - } - private numeric function $deleteByID(required string entityName, required any id, boolean flush=false){ - var count = 0; - - // type safe conversions - arguments.id = convertIDValueToJavaType(entityName=arguments.entityName, id=arguments.id); - - // delete using lowercase id convention from hibernate for identifier - var datasource = orm.getEntityDatasource(arguments.entityName); - var query = orm.getSession(datasource).createQuery("delete FROM #arguments.entityName# where id in (:idlist)"); - query.setParameterList("idlist",arguments.id); - count = query.executeUpdate(); - - // Auto Flush - if( arguments.flush ){ orm.flush(datasource); } - - return count; - } - - /** - * Delete by using an HQL query and iterating via the results, it is not performing a delete query but - * it actually is a select query that should retrieve objects to remove - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - any function deleteByQuery(required string query, any params, numeric max=0, numeric offset=0, boolean flush=false, boolean transactional=getUseTransactions(), string datasource="" ){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$deleteByQuery, arguments); - } - $deleteByQuery( argumentCollection=arguments ); - return this; - } - private any function $deleteByQuery(required string query, any params, numeric max=0, numeric offset=0, boolean flush=false, string datasource=""){ - var objects = arrayNew(1); - var options = {}; - - // Setup query options - if( arguments.offset neq 0 ){ - options.offset = arguments.offset; - } - if( arguments.max neq 0 ){ - options.maxresults = arguments.max; - } - if( Len(arguments.datasource) ){ - options.datasource = arguments.datasource; - } - // Query - if( structKeyExists(arguments, "params") ){ - objects = ORMExecuteQuery(arguments.query, arguments.params, false, options); - } - else{ - objects = ORMExecuteQuery(arguments.query, false, options); - } - - delete(entity=objects,flush=arguments.flush,transactional=arguments.transactional); - return this; - } - - /** - * Deletes entities by using name value pairs as arguments to this function. One mandatory argument is to pass the 'entityName'. - * The rest of the arguments are used in the where class using AND notation and parameterized. - * Ex: deleteWhere(entityName="User",age="4",isActive=true); - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - numeric function deleteWhere(required string entityName,boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - structDelete(arguments,"transactional"); - return $transactioned(variables.$deleteWhere, arguments); - } - structDelete(arguments,"transactional"); - return $deleteWhere( argumentCollection=arguments ); - } - private numeric function $deleteWhere(required string entityName){ - var buffer = createObject("java","java.lang.StringBuffer").init(''); - var key = ""; - var operator = "AND"; - var params = {}; - var idx = 1; - var count = 0; - var options = {}; - - options.datasource = orm.getEntityDatasource(arguments.entityName); - - buffer.append('delete from #arguments.entityName#'); - - // Do we have arguments? - if( structCount(arguments) gt 1){ - buffer.append(" WHERE"); - } - else{ - throw(message="No where arguments sent, aborting deletion", - detail="We will not do a full delete via this method, you need to pass in named value arguments.", - type="BaseORMService.NoWhereArgumentsFound"); - } - - // Go over Params - for(key in arguments){ - // Build where parameterized - if( key neq "entityName" ){ - params[key] = arguments[key]; - buffer.append(" #key# = :#key#"); - idx++; - // Check AND? - if( idx neq structCount(arguments) ){ - buffer.append(" AND"); - } - } - } - - //start DLM deleteion - try{ - count = ORMExecuteQuery( buffer.toString(), params, true, options); - } - catch("java.lang.NullPointerException" e){ - throw(message="A null pointer exception occurred when running the query", - detail="The most likely reason is that the keys in the passed in structure need to be case sensitive. Passed Keys=#structKeyList(params)#", - type="BaseORMService.MaybeInvalidParamCaseException"); - } - catch(any e){ - rethrow; - } - return count; - } - - /** - * Saves an array of passed entities in specified order - * @entities An array of entities to save - * Transactions are used if useTransactions bit is set or the transactional argument is passed - */ - any function saveAll(required entities, forceInsert=false, flush=false,boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$saveAll, arguments); - } - return $saveAll( argumentCollection=arguments ); - } - private any function $saveAll(required entities, forceInsert=false, flush=false){ - var count = arrayLen(arguments.entities); - var eventHandling = getEventHandling(); - - // iterate and save - for(var x=1; x lte count; x++){ - // Event Handling? If enabled, call the preSave() interception - if( eventHandling ){ - ORMEventHandler.preSave( arguments.entities[x] ); - } - // Save it - entitySave(arguments.entities[x], arguments.forceInsert); - // Event Handling? If enabled, call the postSave() interception - if( eventHandling ){ - ORMEventHandler.postSave( arguments.entities[x] ); - } - // Auto Flush - if( arguments.flush ){ orm.flush( orm.getEntityDatasource( arguments.entities[x] ) ); } - } - - return true; - } - - /** - * Save an entity using hibernate transactions or not. You can optionally flush the session also - */ - any function save(required any entity, boolean forceInsert=false, boolean flush=false, boolean transactional=getUseTransactions()){ - // using transaction closure, well, semy closures :( - if( arguments.transactional ){ - return $transactioned(variables.$save, arguments); - } - return $save( argumentCollection=arguments ); - } - any function $save(required any entity, boolean forceInsert=false, boolean flush=false){ - // Event handling flag - var eventHandling = getEventHandling(); - - // Event Handling? If enabled, call the preSave() interception - if( eventHandling ){ - ORMEventHandler.preSave( arguments.entity ); - } - - // save - entitySave(arguments.entity, arguments.forceInsert); - - // Auto Flush - if( arguments.flush ){ orm.flush(orm.getEntityDatasource(arguments.entity)); } - - // Event Handling? If enabled, call the postSave() interception - if( eventHandling ){ - ORMEventHandler.postSave( arguments.entity ); - } - - return true; - } - - /** - * Return the count of records in the DB for the given entity name. You can also pass an optional where statement - * that can filter the count. Ex: count('User','age > 40 AND name="joe"'). You can even use params with this method: - * Ex: count('User','age > ? AND name = ?',[40,"joe"]) - */ - numeric function count(required string entityName,string where="", any params=structNew()){ - var buffer = createObject("java","java.lang.StringBuffer").init(''); - var key = ""; - var operator = "AND"; - var options = {}; - - options.datasource = orm.getEntityDatasource(arguments.entityName); - - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - buffer.append('select count(*) from #arguments.entityName#'); - - // build params - if( len(trim(arguments.where)) ){ - buffer.append(" WHERE #arguments.where#"); - } - - // execute query as unique for the count - try{ - return ORMExecuteQuery( buffer.toString(), arguments.params, true, options); - } - catch("java.lang.NullPointerException" e){ - throw(message="A null pointer exception occurred when running the query", - detail="The most likely reason is that the keys in the passed in structure need to be case sensitive. Passed Keys=#structKeyList(arguments.params)#", - type="ORMService.MaybeInvalidParamCaseException"); - } - - } - - /** - * Returns the count by passing name value pairs as arguments to this function. One mandatory argument is to pass the 'entityName'. - * The rest of the arguments are used in the where class using AND notation and parameterized. - * Ex: countWhere(entityName="User",age="20"); - */ - numeric function countWhere(required string entityName){ - var buffer = createObject("java","java.lang.StringBuffer").init(''); - var key = ""; - var operator = "AND"; - var params = {}; - var idx = 1; - var options = {}; - - options.datasource = orm.getEntityDatasource(arguments.entityName); - - buffer.append('select count(*) from #arguments.entityName#'); - - // Do we have params? - if( structCount(arguments) gt 1){ - buffer.append(" WHERE"); - } - // Go over Params - for(key in arguments){ - // Build where parameterized - if( key neq "entityName" ){ - params[key] = arguments[key]; - buffer.append(" #key# = :#key#"); - idx++; - // Check AND? - if( idx neq structCount(arguments) ){ - buffer.append(" AND"); - } - } - } - // Caching? - if( getUseQueryCaching() ){ - options.cacheName = getQueryCacheRegion(); - options.cacheable = true; - } - - // execute query as unique for the count - try{ - return ORMExecuteQuery( buffer.toString(), params, true, options); - } - catch("java.lang.NullPointerException" e){ - throw(message="A null pointer exception occurred when running the count", - detail="The most likely reason is that the keys in the passed in structure need to be case sensitive. Passed Keys=#structKeyList(params)#", - type="ORMService.MaybeInvalidParamCaseException"); - } - } - - /** - * Evict an entity from session, the id can be a string or structure for the primary key - * You can also pass in a collection name to evict from the collection - */ - any function evict(required string entityName,string collectionName, any id){ - - //Collection? - if( structKeyExists(arguments,"collectionName") ){ - if( structKeyExists(arguments,"id") ) - ORMEvictCollection(arguments.entityName,arguments.collectionName, arguments.id); - else - ORMEvictCollection(arguments.entityName,arguments.collectionName); - } - // Single Entity - else{ - if( structKeyExists(arguments,"id") ) - evictEntity( this.get(entityName=arguments.entityName,id=arguments.id) ); - else - evictEntity( this.new(entityName=arguments.entityName) ); - } - - return this; - } - - /** - * Evict entity objects from session. - * @entities The argument can be one persistence entity or an array of entities - */ - any function evictEntity(required any entities){ - var objects = arrayNew(1); - - if( not isArray(arguments.entities) ){ - arrayAppend(objects, arguments.entities); - } - else{ - objects = arguments.entities; - } - - for( var x=1; x lte arrayLen(objects); x++){ - orm.getSession(orm.getEntityDatasource(objects[x])).evict( objects[x] ); - } - - return this; - } - - /** - * Evict all queries in the default cache or the cache region passed - */ - any function evictQueries(string cacheName, string datasource){ - orm.evictQueries( argumentCollection=arguments ); - return this; - } - - /** - * Merge an entity or array of entities back into the session - */ - any function merge(required any entity){ - var objects = []; - - if( not isArray( arguments.entity ) ){ - arrayAppend( objects, arguments.entity ); - } - else{ - objects = arguments.entity; - } - - for( var x=1; x lte arrayLen( objects ); x++){ - entityMerge( objects[ x ] ); - } - - return this; - } - - /** - * Clear the session removes all the entities that are loaded or created in the session. - * This clears the first level cache and removes the objects that are not yet saved to the database. - */ - any function clear(string datasource=orm.getDefaultDatasource()){ - orm.clearSession(arguments.datasource); - return this; - } - - /** - * Checks if the session contains dirty objects that are awaiting persistence - */ - boolean function isSessionDirty(string datasource=orm.getDefaultDatasource()){ - return orm.getSession(arguments.datasource).isDirty(); - } - - /** - * Checks if the current session contains the passed in entity - */ - boolean function sessionContains(required any entity){ - var ormSession = orm.getSession(orm.getEntityDatasource(arguments.entity)); - // weird CFML thing - return ormSession.contains(arguments.entity); - } - - /** - * Information about the first-level (session) cache for the current session - */ - struct function getSessionStatistics(string datasource=orm.getDefaultDatasource()){ - var stats = orm.getSession(arguments.datasource).getStatistics(); - var results = { - collectionCount = stats.getCollectionCount(), - collectionKeys = stats.getCollectionKeys().toString(), - entityCount = stats.getEntityCount(), - entityKeys = stats.getEntityKeys().toString() - }; - - return results; - } - - /** - * A nice onMissingMethod template to create awesome dynamic methods. - */ - any function onMissingMethod(string missingMethodName, struct missingMethodArguments){ - var method = arguments.missingMethodName; - var args = arguments.missingMethodArguments; - - // Dynamic Find Unique Finders - if( left( method, 6 ) eq "findBy" and len( method ) GT 6 ){ - return findDynamically(missingMethodName=right( method, len( method ) - 6 ), missingMethodArguments=args, unique=true); - } - // Dynamic find All Finders - if( left( method, 9 ) eq "findAllBy" and len( method ) GT 9 ){ - return findDynamically(missingMethodName=right( method, len( method ) - 9 ), missingMethodArguments=args, unique=false); - } - // Dynamic countBy Finders - if( left( method, 7 ) eq "countBy" and len( method ) GT 7 ){ - return findDynamically(missingMethodName=right( method, len( method ) - 7 ), missingMethodArguments=args, unique=true, isCounting=true); - } - - // Throw exception, method not found. - throw(message="Invalid method call: #method#", detail="The dynamic/static method you called does not exist", type="BaseORMService.MissingMethodException"); - } - - /** - * Compile HQL from a dynamic method call - */ - private any function compileHQLFromDynamicMethod(string missingMethodName, struct missingMethodArguments, boolean unique=true, boolean isCounting=false, struct params, entityName){ - var method = arguments.missingMethodName; - var args = arguments.missingMethodArguments; - - // Get all real property names - var realPropertyNames = getPropertyNames( arguments.entityName ); - // Match our method gramars ini the method string - var methodGrammars = REMatchNoCase( "((?!(and|or|$))\w)+(#ALL_CONDITIONALS_REGEX#)?(and|or|$)", method ); - - // Throw exception if no method grammars found - if( !arrayLen( methodGrammars ) ){ - throw(message="Invalid dynamic method grammar expression. Please check your syntax. You could be missing property names or conditionals", - detail="Expression: #method#", - type="BaseORMService.InvalidMethodGrammar"); - } - - // Iterate over method grammars to build HQL Expressions - var HQLExpressions = []; - for( var thisGrammar in methodGrammars ){ - // create expression syntax - var expression = { property = "", conditional = "eq", operator = "and", sql = "=" }; - - // Check for Or expression, AND is default expression - if( right( thisGrammar, 2 ) eq "or" ){ - expression.operator = "or"; - } - // Remove operator now that we have it - thisGrammar = REReplacenoCase( thisGrammar, "(and|or)$", "" ); - - // Get property by removing conditionals from the expression - expression.property = REReplacenoCase( thisGrammar, "(#ALL_CONDITIONALS_REGEX#)$", "" ); - // Verify if property exists in valid properties - // TODO: Add relationships later - var realPropertyIndex = arrayFindNoCase( realPropertyNames, expression.property ); - if( realPropertyIndex EQ 0 ){ - throw(message="The property you requested #expression.property# is not a valid property in the #arguments.entityName# entity", - detail="Valid properties are #arrayToList( realPropertyNames )#", - type="BaseORMService.InvalidEntityProperty"); - } - // now save the actual property name to the passed in property to avoid case issues with Hibernate - expression.property = realPropertyNames[ realPropertyIndex ]; - // Remove property now from method expression - thisGrammar = REReplacenoCase( thisGrammar, "#expression.property#", "" ); - - // Get Conditional Operator now if it exists, else it defaults to EQ - if( len( thisGrammar ) ){ - // Match the conditional statement - var conditional = REMatchNoCase( "(#ALL_CONDITIONALS_REGEX#)$", thisGrammar ); - // Did we match? - if( arrayLen( conditional ) ){ - expression.conditional = conditional[ 1 ]; - expression.sql = CONDITIONALS_SQL_MAP[ expression.conditional ]; - } - else{ - throw(message="Invalid conditional statement in method expression: #thisGrammar#", - detail="Valid Conditionals: #ALL_CONDITIONALS#", - type="BaseORMService.InvalidConditionalExpression"); - } - } - - // Add to expressions - arrayAppend( HQLExpressions, expression ); - } - // end compile grammars - - // Build the HQL - var where = ""; - // Begin building the hql statement with or without counts - var hql = ""; - if( arguments.isCounting ){ - hql &= "select count(id) "; - } - hql &= "from " & arguments.entityName; - - var paramIndex = 1; - for( var thisExpression in HQLExpressions ){ - if( len( where ) ){ - where = "#where# #thisExpression.operator# "; - } - switch( trim( thisExpression.conditional ) ){ - case "isNull" : case "isNotNull" : { - where = "#where# #thisExpression.property# #thisExpression.sql#"; - break; - } - case "between" : case "notBetween" : { - where = "#where# #thisExpression.property# #thisExpression.sql# :param#paramIndex++# and :param#paramIndex++#"; - break; - } - case "inList" : case "notInList" : { - where = "#where# #thisExpression.property# #thisExpression.sql# (:param#paramIndex++#)"; - // Verify if the param is an array collection - if( isSimpleValue( params["param#paramIndex-1#"] ) ){ - params["param#paramIndex-1#"] = listToArray( params["param#paramIndex-1#"] ); - } - break; - } - default:{ - where = "#where# #thisExpression.property# #thisExpression.sql# :param#paramIndex++#"; - break; - } - } - } - - // Finalize the HQL - return hql & " where #where#"; - } - - /** - * A method for finding entity's dynamically, for example: - * findByLastNameAndFirstName('User', 'Tester', 'Test'); - * findByLastNameOrFirstName('User', 'Tester', 'Test') - * findAllByLastNameIsNotNull('User'); - * The first argument must be the 'entityName' or a named agument called 'entityname' - * Any argument which is a structure will be used as options for the query: { ignorecase, maxresults, offset, cacheable, cachename, timeout } - */ - any function findDynamically(string missingMethodName, struct missingMethodArguments, boolean unique=true, boolean isCounting=false){ - var method = arguments.missingMethodName; - var args = arguments.missingMethodArguments; - var dynamicCacheKey = hash( arguments.toString() ); - var hql = ""; - - // setup the params to bind from the arguments, and also distinguish the incoming query options - var params = {}; - var options = {}; - // Verify entityName, if does not exist, use the first argument. - if( !structKeyExists(args, "entityName" ) ){ - arguments.entityName = args[ 1 ]; - // Remove it like a mighty ninja - structDelete( args, "1" ); - } - else{ - arguments.entityName = args.entityName; - // Remove it like a mighty ninja - structDelete( args, "entityName" ); - } - // Process arguments to binding parameters, we use named as they bind better in HQL, go figure - for(var i=1; i LTE ArrayLen( args ); i++){ - // Check if the argument is a structure, if it is, then these are the query options - if( isStruct( args[ i ] ) ){ - options = args[ i ]; - } - // Normal params - else{ - params[ "param#i#" ] = args[ i ]; - } - } - // Check if we have already the signature for this request - if( structKeyExists( HQLDynamicCache, dynamicCacheKey ) ){ - hql = HQLDynamicCache[ dynamicCacheKey ]; - } - else{ - arguments.params = params; - hql = compileHQLFromDynamicMethod( argumentCollection=arguments ); - // store compiled HQL - HQLDynamicCache[ dynamicCacheKey ] = hql; - } - - //results struct used for testing - var results = structNew(); - results.method = method; - results.params = params; - results.options = options; - results.unique = arguments.unique; - results.isCounting = arguments.isCounting; - results.hql = hql; - - //writeDump( ORMExecuteQuery( hql, params, arguments.unique, options) ); - //writeDump(results);abort; - - // execute query as unique for the count - try{ - return ORMExecuteQuery( hql, params, arguments.unique, options); - } - catch(Any e){ - if( findNoCase("org.hibernate.NonUniqueResultException", e.detail) ){ - throw(message=e.message & e.detail, - detail="If you do not want unique results then use 'FindAllBy' instead of 'FindBy'", - type="ORMService.NonUniqueResultException"); - } - throw(message=e.message & e.detail, type="BaseORMService.HQLQueryException", detail="Dynamic compiled query: #results.toString()#"); - } - - } - - - /** - * Returns the key (id field) of a given entity, either simple or composite keys. - * If the key is a simple pk then it will return a string, if it is a composite key then it returns an array - */ - any function getKey(required string entityName){ - var hibernateMD = orm.getSessionFactory(orm.getEntityDatasource(arguments.entityName)).getClassMetaData(arguments.entityName); - - // Is this a simple key? - if( hibernateMD.hasIdentifierProperty() ){ - return hibernateMD.getIdentifierPropertyName(); - } - - // Composite Keys? - if( hibernateMD.getIdentifierType().isComponentType() ){ - // Do conversion to CF Array instead of java array, just in case - return listToArray(arrayToList(hibernateMD.getIdentifierType().getPropertyNames())); - } - - return ""; - } - - /** - * Returns the Property Names of the entity via hibernate metadata - */ - array function getPropertyNames(required string entityName){ - return orm.getSessionFactory( orm.getEntityDatasource(arguments.entityName) ).getClassMetaData( arguments.entityName ).getPropertyNames(); - } - - /** - * Returns the table name that the current entity string belongs to via hibernate metadata - */ - string function getTableName(required string entityName){ - return orm.getSessionFactory( orm.getEntityDatasource(arguments.entityName) ).getClassMetadata( arguments.entityName ).getTableName(); - } - - /** - * Returns the entity name from a given entity object via session lookup or if new object via metadata lookup - */ - function getEntityGivenName(required entity) { - if( sessionContains( arguments.entity ) ){ - return orm.getSession( orm.getEntityDatasource(arguments.entity) ).getEntityName( entity ); - } - - // else long approach - var md = getMetadata( arguments.entity ); - if( structKeyExists(md, "entityname") ){ return md.entityname; } - return listLast( md.name, "."); - } - - /** - * Coverts an ID, list of ID's, or array of ID's values to the proper java type - * The method returns a coverted array of ID's - */ - any function convertIDValueToJavaType(required entityName, required id){ - var hibernateMD = orm.getSessionFactory(orm.getEntityDatasource(arguments.entityName)).getClassMetaData(arguments.entityName); - - if(isDefined("hibernateMD") and not hibernateMD.getIdentifierType().isComponentType() ){ - //id conversion to array - if( isSimpleValue(arguments.id) ){ - arguments.id = listToArray(arguments.id); - } - - // Convert to hibernate native types - for (var i=1; i lte arrayLen(arguments.id); i=i+1){ - arguments.id[i] = hibernateMD.getIdentifierType().fromStringValue(arguments.id[i]); - } - } - - return arguments.id; - } - - /** - * Coverts a value to the correct javaType for the property passed in - * The method returns the value in the proper Java Type - */ - any function convertValueToJavaType(required entityName, required propertyName, required value){ - var hibernateMD = orm.getSessionFactory(orm.getEntityDatasource(arguments.entityName)).getClassMetaData(arguments.entityName); - - return hibernateMD.getPropertyType(arguments.propertyName).fromStringValue(arguments.value); - } - - /** - * Get our hibernate org.hibernate.criterion.Restrictions proxy object - */ - public any function getRestrictions(){ - return restrictions; - } - - /** - * Do a hibernate criteria based query with projections. You must pass an array of criterion objects by using the Hibernate Restrictions object that can be retrieved from this service using ''getRestrictions()''. The Criteria interface allows to create and execute object-oriented queries. It is powerful alternative to the HQL but has own limitations. Criteria Query is used mostly in case of multi criteria search screens, where HQL is not very effective. - */ - public any function criteriaQuery(required entityName, - array criteria=ArrayNew(1), - string sortOrder="", - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignoreCase=false, - boolean asQuery=getDefaultAsQuery()){ - // create Criteria query object - var qry = createCriteriaQuery(arguments.entityName, arguments.criteria); - - // Setup listing options - if( arguments.offset NEQ 0 ){ - qry.setFirstResult(arguments.offset); - } - if(arguments.max GT 0){ - qry.setMaxResults(arguments.max); - } - if( arguments.timeout NEQ 0 ){ - qry.setTimeout(arguments.timeout); - } - - // Caching - if( getUseQueryCaching() ){ - qry.setCacheRegion(getQueryCacheRegion()); - qry.setCacheable(true); - } - - // Sort Order Case - if( Len(Trim(arguments.sortOrder)) ){ - var sortTypes = listToArray(arguments.sortOrder); - for(var sortType in sortTypes) { - var sortField = Trim(ListFirst(sortType," ")); - var sortDir = "ASC"; - var Order = CreateObject("java","org.hibernate.criterion.Order"); - - if(ListLen(sortType," ") GTE 2){ - sortDir = ListGetAt(sortType,2," "); - } - - switch(UCase(sortDir)) { - case "DESC": - var orderBy = Order.desc(sortField); - break; - default: - var orderBy = Order.asc(sortField); - break; - } - // ignore case - if(arguments.ignoreCase){ - orderBy.ignoreCase(); - } - // add order to query - qry.addOrder(orderBy); - } - } - - // Get listing - var results = qry.list(); - - // Is it Null? If yes, return empty array - if( isNull(results) ){ results = []; } - - // Objects or Query? - if( arguments.asQuery ){ - results = EntityToQuery(results); - } - - return results; - } - - /** - * Get the record count using hibernate projections and criterion for specific queries - */ - numeric function criteriaCount(required entityName, array criteria=ArrayNew(1)){ - // create a new criteria query object - var qry = createCriteriaQuery(arguments.entityName, arguments.criteria); - var projections = CreateObject("java","org.hibernate.criterion.Projections"); - - qry.setProjection( projections.rowCount() ); - - return qry.uniqueResult(); - } - - /** - * Get a brand new criteria builder object - * @entityName The name of the entity to bind this criteria query to - * @useQueryCaching Activate query caching for the list operations - * @queryCacheRegion The query cache region to use, which defaults to criterias.{entityName} - * @defaultAsQuery To return results as queries or array of objects or reports, default is array as results might not match entities precisely - */ - any function newCriteria( - required string entityName, - boolean useQueryCaching=false, - string queryCacheRegion="" - ){ - - // mix in yourself as a dependency - arguments.ORMService = this; - // create new criteria builder - return new CriteriaBuilder( argumentCollection=arguments ); - } - - /** - * Create a new hibernate criteria object according to entityname and criterion array objects - */ - private any function createCriteriaQuery(required entityName, array criteria=ArrayNew(1)){ - var qry = orm.getSession(orm.getEntityDatasource(arguments.entityName)).createCriteria( arguments.entityName ); - - for(var i=1; i LTE ArrayLen(arguments.criteria); i++) { - if( isSimpleValue( arguments.criteria[i] ) ){ - // create criteria out of simple values for associations with alias - qry.createCriteria( arguments.criteria[i], arguments.criteria[i] ); - } - else{ - // add criterion - qry.add( arguments.criteria[i] ); - } - } - - return qry; - } - - /** - * My hibernate safe transaction closure wrapper - * @method the method to closure - * @argCollection the arguments to passthrough - */ - private any function $transactioned( required method, argCollection=structnew() ){ - // Are we already in a transaction? - if( structKeyExists(request,"cbox_aop_transaction") ){ - return arguments.method(argumentCollection=arguments.argCollection); - } - - // transaction safe call, start one - // mark transaction began - request["cbox_aop_transaction"] = true; - transaction{ - - try{ - // Call method - results = arguments.method(argumentCollection=arguments.argCollection); - // commit transaction - transactionCommit(); - } - catch(Any e){ - // remove pointer - structDelete(request,"cbox_aop_transaction"); - // RollBack Transaction - transactionRollback(); - //throw it - rethrow; - } - - } - - // remove pointer, out of transaction now. - structDelete(request,"cbox_aop_transaction"); - // Results? If found, return them. - if( NOT isNull(results) ){ return results; } - - } -} diff --git a/src/cfml/system/wirebox/system/orm/hibernate/CriteriaBuilder.cfc b/src/cfml/system/wirebox/system/orm/hibernate/CriteriaBuilder.cfc deleted file mode 100644 index 085f6b3d3..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/CriteriaBuilder.cfc +++ /dev/null @@ -1,309 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** - -Author : Luis Majano -Description : - This is the ColdBox Criteria Builder Class that helps you create a nice programmatic - DSL language for building hibernate criteria queries and projections without the added - complexities. - -We also setup several public properties: - -this.PROJECTIONS - Maps to the Hibernate projections class: org.hibernate.criterion.Projections -this.RESTRICTIONS - Maps to our ColdBox restrictions class: wirebox.system.orm.hibernate.criterion.Restrictions - -Join Types -this.FULL_JOIN - Specifies joining to an entity based on a full join. -this.INNER_JOIN - Specifies joining to an entity based on an inner join. -this.LEFT_JOIN - Specifies joining to an entity based on a left outer join. - -Result Transformers -this.ALIAS_TO_ENTITY_MAP - Each row of results is a Map from alias to entity instance -this.DISTINCT_ROOT_ENTITY - Each row of results is a distinct instance of the root entity -this.PROJECTION - This result transformer is selected implicitly by calling setProjection() -this.ROOT_ENTITY - Each row of results is an instance of the root entity - -*/ -import wirebox.system.orm.hibernate.*; -component accessors="true" extends="wirebox.system.orm.hibernate.BaseBuilder" { - - // The criteria values this criteria builder builds upon. - property name="criterias" type="array"; - // The queryCacheRegion name property for all queries in this criteria object - property name="queryCacheRegion" type="string" default="criterias.{entityName}"; - // The bit that tells the service to enable query caching, disabled by default - property name="useQueryCaching" type="boolean" default="false"; - -/************************************** Constructor *********************************************/ - - // Constructor - CriteriaBuilder function init( - required string entityName, - boolean useQueryCaching=false, - string queryCacheRegion="", - required any ORMService - ){ - - // Determine datasource for given entityName - var orm = getORMUtil(); - var datasource = orm.getEntityDatasource( arguments.entityName ); - - // setup basebuilder with criteria query and restrictions - super.init( entityName=arguments.entityName, - criteria=orm.getSession( datasource ).createCriteria( arguments.entityName ), - restrictions=new criterion.Restrictions(), - ORMService=arguments.ORMService ); - - // local criterion values - variables.criterias = []; - // caching? - variables.useQueryCaching = arguments.useQueryCaching; - // caching region? - if( len( trim( arguments.queryCacheRegion ) ) EQ 0 ){ - arguments.queryCacheRegion = "criterias.#arguments.entityName#"; - } - variables.queryCacheRegion = arguments.queryCacheRegion; - - return this; - } - -/************************************** PUBLIC *********************************************/ - - /** - * Execute the criteria queries you have defined and return the results, you can pass optional parameters or define them via our methods - */ - any function list(numeric offset=0, - numeric max=0, - numeric timeout=0, - string sortOrder="", - boolean ignoreCase=false, - boolean asQuery=false){ - - // Setup listing options - if( arguments.offset NEQ 0 ){ - firstResult(arguments.offset); - } - if(arguments.max GT 0){ - maxResults(arguments.max); - } - if( arguments.timeout NEQ 0 ){ - this.timeout(arguments.timeout); - } - - // Caching - if( getUseQueryCaching() ){ - cache(true,getQueryCacheRegion()); - } - - // Sort Order - if( Len(Trim(arguments.sortOrder)) ){ - normalizeOrder( arguments.sortOrder, arguments.ignoreCase ); - } - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "beforeCriteriaBuilderList", { - "criteriaBuilder" = this - }); - } - - // Get listing - var results = nativeCriteria.list(); - - // Is it Null? If yes, return empty array - if( isNull(results) ){ results = []; } - - // Objects or Query? - if( arguments.asQuery ){ - results = EntityToQuery(results); - } - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "afterCriteriaBuilderList", { - "criteriaBuilder" = this, - "results" = results - }); - } - return results; - } - - // pass off arguments to higher-level restriction builder, and handle the results - any function onMissingMethod(required string missingMethodName, required struct missingMethodArguments) { - // get the restriction/new criteria - var r = createRestriction( argumentCollection=arguments ); - // switch on the object type - switch( getMetaData( r ).name ) { - // if it's a builder, just return this - case 'wirebox.system.orm.hibernate.CriteriaBuilder': - break; - // everything else is a real restriction; add it to native criteria, then return this - default: - nativeCriteria.add( r ); - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Restriction", - "criteriaBuilder" = this - }); - } - - break; - } - return this; - } - - // create an instance of a detached criteriabuilder that can be added, like criteria, to the main criteria builder - any function createSubcriteria( required string entityName, string alias="" ) { - // create detached builder - arguments.ORMService = variables.ORMService; - var subcriteria = new DetachedCriteriaBuilder( argumentCollection=arguments ); - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Subquery", - "criteriaBuilder" = this - }); - } - - // return the subscriteria instance so we can keep chaining methods to it, but rooted to the subcriteria - return subcriteria; - } - - // Enable caching of this query result, provided query caching is enabled for the underlying session factory. - any function cache(required boolean cache=true,string cacheRegion){ - nativeCriteria.setCacheable( javaCast("boolean", arguments.cache) ); - if( structKeyExists(arguments,"cacheRegion") ){ - nativeCriteria.setCacheRegion( arguments.cacheRegion ); - } - return this; - } - - // Set the name of the cache region to use for query result caching. - any function cacheRegion(required string cacheRegion){ - nativeCriteria.setCacheRegion( arguments.cacheRegion ); - return this; - } - - // Set a fetch size for the underlying JDBC query. - any function fetchSize(required numeric fetchSize){ - nativeCriteria.setFetchSize( javaCast("int", arguments.fetchSize) ); - return this; - } - - // Set the first result to be retrieved or the offset integer - any function firstResult(required numeric firstResult){ - nativeCriteria.setFirstResult( javaCast("int", arguments.firstResult) ); - if( SQLHelper.canLogLimitOffset() ) { - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Offset", - "criteriaBuilder" = this - }); - } - - } - return this; - } - - // Set a limit upon the number of objects to be retrieved. - any function maxResults(required numeric maxResults){ - nativeCriteria.setMaxResults( javaCast("int", arguments.maxResults) ); - if( SQLHelper.canLogLimitOffset() ) { - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Max", - "criteriaBuilder" = this - }); - } - - } - return this; - } - - // Set the read-only/modifiable mode for entities and proxies loaded by this Criteria, defaults to readOnly=true - any function readOnly(boolean readOnly=true){ - nativeCriteria.setReadOnly( javaCast("boolean", arguments.readOnly) ); - return this; - } - - // Set a timeout for the underlying JDBC query. - any function timeout(required numeric timeout){ - nativeCriteria.setTimeout( javaCast("int", arguments.timeout) ); - return this; - } - - // Convenience method to return a single instance that matches the built up criterias query, or null if the query returns no results. - any function get(){ - return nativeCriteria.uniqueResult(); - } - - /** - * Get the record count using hibernate projections for the given criterias - * @propertyName The name of the property to do the count on or do it for all row results instead - */ - numeric function count(propertyName=""){ - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "beforeCriteriaBuilderCount", { - "criteriaBuilder" = this - }); - } - // else project on the local criterias - if( len( arguments.propertyName ) ){ - nativeCriteria.setProjection( this.projections.countDistinct( arguments.propertyName ) ); - } - else{ - nativeCriteria.setProjection( this.projections.distinct( this.projections.rowCount() ) ); - } - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Count", - "criteriaBuilder" = this - }); - } - - var results = nativeCriteria.uniqueResult(); - // clear count like a ninja, so we can reuse this criteria object. - nativeCriteria.setProjection( javacast("null","") ); - nativeCriteria.setResultTransformer( this.ROOT_ENTITY ); - - // process interception - if( ORMService.getEventHandling() ){ - variables.eventManager.processState( "afterCriteriaBuilderCount", { - "criteriaBuilder" = this, - "results" = results - }); - } - - return results; - } - - /************************************** PRIVATE *********************************************/ - - /** - * Get ORM Util - */ - private function getORMUtil() { - return new wirebox.system.orm.hibernate.util.ORMUtilFactory().getORMUtil(); - } - -} diff --git a/src/cfml/system/wirebox/system/orm/hibernate/DetachedCriteriaBuilder.cfc b/src/cfml/system/wirebox/system/orm/hibernate/DetachedCriteriaBuilder.cfc deleted file mode 100644 index 258caffeb..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/DetachedCriteriaBuilder.cfc +++ /dev/null @@ -1,80 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** - -Description : - Based on the general approach of CriteriaBuilder.cfc, DetachedCriteriaBuilder allows you - to create a detached criteria query that can be used: - * in conjuction with critierion.Subqueries to add a programmatically built subquery as a criterion of another criteria query - * as a detachedSQLProjection, which allows you to build a programmatic subquery that is added as a projection to another criteria query -*/ -import wirebox.system.orm.hibernate.*; -component accessors="true" extends="wirebox.system.orm.hibernate.BaseBuilder" { - - /** - * Constructor - */ - DetachedCriteriaBuilder function init( - required string entityName, - required string alias, - required any ORMService - ){ - // create new DetachedCriteria - var criteria = createObject( "java", "org.hibernate.criterion.DetachedCriteria" ).forEntityName( arguments.entityName, arguments.alias ); - - // setup base builder with detached criteria and subqueries - super.init( entityName=arguments.entityName, - criteria=criteria, - restrictions=new criterion.Subqueries( criteria ), - ORMService=arguments.ORMService ); - - return this; - } - - // pass off arguments to higher-level restriction builder, and handle the results - any function onMissingMethod( required string missingMethodName, required struct missingMethodArguments ) { - // get the restriction/new criteria - var r = createRestriction( argumentCollection=arguments ); - // switch on the object type - switch( getMetaData( r ).name ) { - // if a detached criteria builder, just return this so we can keep chaining - case 'wirebox.system.orm.hibernate.DetachedCriteriaBuilder': - break; - // if a subquery, we *need* to return the restrictino itself, or bad things happen - case 'org.hibernate.criterion.PropertySubqueryExpression': - case 'org.hibernate.criterion.ExistsSubqueryExpression': - case 'org.hibernate.criterion.SimpleSubqueryExpression': - return r; - // otherwise, just a restriction; add it to nativeCriteria, then return this so we can keep chaining - default: - nativeCriteria.add( r ); - // process interception - variables.eventManager.processState( "onCriteriaBuilderAddition", { - "type" = "Subquery Restriction", - "CriteriaBuilder" = this - }); - break; - } - return this; - } - - public any function getNativeCriteria() { - var ormsession = variables.ORMService.getORM().getSession(); - return variables.nativeCriteria.getExecutableCriteria( ormsession ); - } - - public any function createDetachedSQLProjection() { - // get the sql with replaced parameters - var sql = SQLHelper.getSql( returnExecutableSql=true ); - var alias = SQLHelper.getProjectionAlias(); - var uniqueAlias = SQLHelper.generateSQLAlias(); - // by default, alias is this_...convert it to the alias provided - sql = replaceNoCase( sql, "this_", SQLHelper.getRootSQLAlias(), 'all' ); - // wrap it up and uniquely alias it - sql = "( #sql# ) as " & alias; - // now that we have the sql string, we can create the sqlProjection - return this.PROJECTIONS.sqlProjection( sql, [ alias ], SQLHelper.getProjectedTypes() ); - } -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/VirtualEntityService.cfc b/src/cfml/system/wirebox/system/orm/hibernate/VirtualEntityService.cfc deleted file mode 100644 index 560a52c21..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/VirtualEntityService.cfc +++ /dev/null @@ -1,240 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Curt Gratz & Luis Majano -Description : - -This is a Virtual Entity Service that extends the Coldbox BaseORMService to -provide easy access to creating virtual services that extend the BaseORMService - -For example, if you want a UserService, you can either create an object based -off this object if no additional functionality is needed like this: - -UserService=CreateObject("component", "wirebox.system.orm.hibernate.VirtualEntityService").init("User"); - -You can also use this virtual service as a template object and extend and override as needed. - -import wirebox.system.orm.hibernate.*; -component extends="VirtualEntityService" -UserService function init(){ - // setup properties - setEntityName('User'); - setQueryCacheRegion( "#arguments.entityName#.defaultVSCache" ); - setUseQueryCaching( false ); - setEventHandling( false ); - setDefaultAsQuery( true ); - return this; -} - -*/ -component extends="wirebox.system.orm.hibernate.BaseORMService" accessors="true"{ - - /** - * The entityName property for this "version" of the Virtual Service - */ - property name="entityName" type="string"; - - /** - * The datasource property for this "version" of the Virtual Service - */ - property name="datasource" type="string"; - - /************************************** CONSTRUCTOR *********************************************/ - - VirtualEntityService function init(required string entityname, - string queryCacheRegion, - boolean useQueryCaching, - boolean eventHandling, - boolean useTransactions, - boolean defaultAsQuery, - string datasource){ - // create cache region - if( !structKeyExists(arguments,"queryCacheRegion") ){ - arguments.queryCacheRegion = "#arguments.entityName#.defaultVSCache"; - } - - // init parent - super.init(argumentCollection=arguments); - - // Set the local entity to be used in this virtual entity service - setEntityName( arguments.entityName ); - - // Set the datasource of the local entity to be used in this virtual entity service - // Only if not passed - if( !StructKeyExists(arguments, "datasource") ){ - setDatasource( orm.getEntityDatasource( arguments.entityName ) ); - } - else{ - setDatasource( arguments.datasource ); - } - - return this; - } - - /************************************** PUBLIC *********************************************/ - - any function executeQuery(required string query, - any params=structnew(), - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignorecase=false, - boolean asQuery=getDefaultAsQuery(), - boolean unique=false){ - - arguments.datasource = this.getDatasource(); - return super.executeQuery(argumentCollection=arguments); - } - - any function list(struct criteria=structnew(), - string sortOrder="", - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignoreCase=false, - boolean asQuery=getDefaultAsQuery()){ - - arguments.entityName = this.getEntityName(); - var results = super.list(argumentCollection=arguments); - return results; - } - - any function findWhere(required struct criteria){ - return super.findWhere(this.getEntityName(), arguments.criteria); - } - - array function findAllWhere(required struct criteria, string sortOrder=""){ - return super.findAllWhere(this.getEntityName(), arguments.criteria, arguments.sortOrder); - } - - any function new(struct properties=structnew(), boolean composeRelationships=true, nullEmptyInclude="", nullEmptyExclude="", boolean ignoreEmpty=false, include="", exclude=""){ - arguments.entityName = this.getEntityName(); - return super.new(argumentCollection=arguments); - } - - boolean function exists(required any id) { - arguments.entityName = this.getEntityName(); - return super.exists(argumentCollection=arguments); - } - - any function get(required any id,boolean returnNew=true) { - arguments.entityName = this.getEntityName(); - return super.get(argumentCollection=arguments); - } - - array function getAll(any id,string sortOrder="") { - arguments.entityName = this.getEntityName(); - return super.getAll(argumentCollection=arguments); - } - - numeric function deleteAll(boolean flush=false,boolean transactional=getUseTransactions()){ - arguments.entityName = this.getEntityName(); - return super.deleteAll(arguments.entityName,arguments.flush); - } - - boolean function deleteByID(required any id, boolean flush=false,boolean transactional=getUseTransactions()){ - arguments.entityName = this.getEntityName(); - return super.deleteByID(argumentCollection=arguments); - } - - any function deleteByQuery(required string query, any params, numeric max=0, numeric offset=0, boolean flush=false, boolean transactional=getUseTransactions() ){ - arguments.datasource = this.getDatasource(); - return super.deleteByQuery(argumentCollection=arguments); - } - - numeric function deleteWhere(boolean transactional=getUseTransactions()){ - arguments.entityName = this.getEntityName(); - return super.deleteWhere(argumentCollection=arguments); - } - - numeric function count(string where="", any params=structNew()){ - arguments.entityName = this.getEntityName(); - return super.count(argumentCollection=arguments); - } - - numeric function countWhere(){ - arguments.entityName = this.getEntityName(); - return super.countWhere(argumentCollection=arguments); - } - - void function evict(string collectionName, any id){ - arguments.entityName = this.getEntityName(); - super.evict(argumentCollection=arguments); - } - - any function clear(string datasource=this.getDatasource()){ - return super.clear(argumentCollection=arguments); - } - - boolean function isSessionDirty(string datasource=this.getDatasource()){ - arguments.datasource = this.getDatasource(); - return super.isSessionDirty(argumentCollection=arguments); - } - - struct function getSessionStatistics(string datasource=this.getDatasource()){ - arguments.datasource = this.getDatasource(); - return super.getSessionStatistics(argumentCollection=arguments); - } - - string function getKey(){ - return super.getKey( this.getEntityName() ); - } - - array function getPropertyNames(){ - return super.getPropertyNames(this.getEntityName()); - } - - string function getTableName(){ - return super.getTableName(this.getEntityName()); - } - - any function criteriaQuery(array criteria=ArrayNew(1), - string sortOrder="", - numeric offset=0, - numeric max=0, - numeric timeout=0, - boolean ignoreCase=false, - boolean asQuery=getDefaultAsQuery()){ - arguments.entityName = this.getEntityName(); - return super.criteriaQuery(argumentCollection=arguments); - } - - numeric function criteriaCount(array criteria=ArrayNew(1)){ - return super.criteriaCount(this.getEntityName(), arguments.criteria); - } - - any function newCriteria(boolean useQueryCaching=false, string queryCacheRegion=""){ - - arguments.entityName = this.getEntityName(); - return super.newCriteria(argumentCollection=arguments); - } - - /** - * Coverts an ID, list of ID's, or array of ID's values to the proper java type - * The method returns a coverted array of ID's - */ - any function convertIDValueToJavaType(required id){ - arguments.entityName = this.getEntityName(); - return super.convertIDValueToJavaType(argumentCollection=arguments); - } - - /** - * Coverts a value to the correct javaType for the property passed in - * The method returns the value in the proper Java Type - */ - any function convertValueToJavaType(required propertyName, required value){ - arguments.entityName = this.getEntityName(); - return super.convertValueToJavaType(argumentCollection=arguments); - } - - /** - * A nice onMissingMethod template to create awesome dynamic methods based on a virtual service - */ - any function onMissingMethod(string missingMethodName, struct missingMethodArguments){ - // Add the entity name - arguments.missingMethodArguments.entityName = this.getEntityName(); - return super.onMissingMethod(argumentCollection=arguments); - } -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/WBEventHandler.cfc b/src/cfml/system/wirebox/system/orm/hibernate/WBEventHandler.cfc deleted file mode 100644 index 9d74bb3ae..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/WBEventHandler.cfc +++ /dev/null @@ -1,206 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Description : - -This class can be used directly or inherited from for more granular control of ORM injections. -This bridges Hibernate to WireBox so you can wire up ORM entities in your application. Please also -note that there is no way to intercept new() or entityNew() or createObject() calls done via -ColdFusion and there is no preNew interception point exposed by ColdFusion. So if you want ORM -entity injection enabled for new entities, you will have to send them manually into wirebox for wiring like so: - -wirebox.autowire( entity ); - -All loaded entities will be wired for you during the postLoad() ORM event handler. - -This event handler will also announce WireBox events according to hibernate events, so you can -create WireBox listeners and perform certain actions on entities. The announced events are: - -- ORMPreLoad -- ORMPostLoad -- ORMPreDelete -- ORMPostDelete -- ORMPreUpdate -- ORMPostUpdate -- ORMPreInsert -- ORMPostInsert -- ORMPreSave -- ORMPostSave - -This class requires that WireBox be in application scope in a key called 'wirebox'. You can -override this key by using a private variable in your own implementation. - -To use: -1) In your Application.cfc orm settings point it directly to this file - this.ormsettings.eventHandling = true; - this.ormsettings.eventHandler = "wirebox.system.orm.hibernate.WBEventHandler"; - -2) Create a CFC that inherits from "wirebox.system.orm.hibernate.WBEventHandler" and place it somewhere in your app. - Add the orm settings in your Application.cfc - this.ormsettings.eventHandling = true; - this.ormsettings.eventHandler = "model.EventHandler"; - -If you do the latter, you can use some extra functionality by using the following private variables. - -// The scope key wirebox is located in application scope -scopeKey = "wirebox"; - -// Include list of ORM entities to include in the injection, if blank it includes all, which is the default -injectorInclude = ""; - -// Exclude list of ORM entities to exclude in the injection, if blank it includes none, which is the default -injectorExclude = ""; - -*/ -component implements="CFIDE.orm.IEventHandler"{ - - /** - * The scope key to use - */ - variables.scopeKey = "wirebox"; - - /** - * Include list of ORM entities to include in the injection, if blank it includes all, which is the default - */ - variables.injectorInclude = ""; - - /** - * Exclude list of ORM entities to exclude in the injection, if blank it includes none, which is the default - */ - variables.injectorExclude = ""; - - /** - * postNew called by ColdBox which in turn announces a coldbox interception: ORMPostNew - */ - public void function postNew( entity, entityName ){ - var args = { entity = arguments.entity, entityName=arguments.entityName }; - processEntityInjection( args.entityName, args.entity ); - announceInterception( "ORMPostNew", args ); - } - - /** - * preLoad called by hibernate which in turn announces a WireBox interception: ORMPreLoad - */ - public void function preLoad( entity ){ - announceInterception( "ORMPreLoad", { entity = arguments.entity } ); - } - - /** - * postLoad called by hibernate which in turn announces a WireBox interception: ORMPostLoad - */ - public void function postLoad( entity ){ - var orm = getORMUtil(); - var datasource = orm.getEntityDatasource( arguments.entity ); - - var args = { entity=arguments.entity, entityName=orm.getSession( datasource ).getEntityName( arguments.entity ) }; - processEntityInjection(args.entityName, args.entity); - announceInterception( "ORMPostLoad",args); - } - - /** - * postDelete called by hibernate which in turn announces a WireBox interception: ORMPostDelete - */ - public void function postDelete( entity ){ - announceInterception( "ORMPostDelete", {entity=arguments.entity}); - } - - /** - * preDelete called by hibernate which in turn announces a WireBox interception: ORMPreDelete - */ - public void function preDelete( entity ) { - announceInterception( "ORMPreDelete", {entity=arguments.entity}); - } - - /** - * preUpdate called by hibernate which in turn announces a WireBox interception: ORMPreUpdate - */ - public void function preUpdate( entity, struct oldData=structNew()){ - announceInterception( "ORMPreUpdate", {entity=arguments.entity, oldData=arguments.oldData}); - } - - /** - * postUpdate called by hibernate which in turn announces a WireBox interception: ORMPostUpdate - */ - public void function postUpdate( entity ){ - announceInterception( "ORMPostUpdate", {entity=arguments.entity}); - } - - /** - * preInsert called by hibernate which in turn announces a WireBox interception: ORMPreInsert - */ - public void function preInsert( entity ){ - announceInterception( "ORMPreInsert", {entity=arguments.entity}); - } - - /** - * postInsert called by hibernate which in turn announces a WireBox interception: ORMPostInsert - */ - public void function postInsert( entity ){ - announceInterception( "ORMPostInsert", {entity=arguments.entity}); - } - - /** - * preSave called by WireBox Base service before save() calls - */ - public void function preSave( entity ){ - announceInterception( "ORMPreSave", {entity=arguments.entity}); - } - - /** - * postSave called by WireBox Base service after transaction commit or rollback via the save() method - */ - public void function postSave( entity ){ - announceInterception( "ORMPostSave", {entity=arguments.entity}); - } - - /** - * Process a wirebox event - */ - public function announceInterception( required string state, data=structNew() ){ - // announce event - getWireBox().getEventManager().processState( arguments.state, arguments.data ); - } - - /** - * Get the system Event Manager - */ - public function getEventManager(){ - return getWireBox().getEventManager(); - } - - /************************************** PRIVATE *********************************************/ - - /** - * Get a reference to WireBox - */ - private function getWireBox(){ - return application[ scopeKey ]; - } - - /** - * Process entity injection - */ - private function processEntityInjection(required entityName,required entity){ - - // Include,Exclude? - if( (len(injectorInclude) AND listContainsNoCase(injectorInclude,entityName)) - OR - (len(injectorExclude) AND NOT listContainsNoCase(injectorExclude,entityName)) - OR - (NOT len(injectorInclude) AND NOT len(injectorExclude) ) ){ - - // Process DI - getWireBox().autowire(target=entity,targetID="ORMEntity-#entityName#"); - } - } - - /** - * Get ORM Util - */ - private function getORMUtil() { - return new wirebox.system.orm.hibernate.util.ORMUtilFactory().getORMUtil(); - } - -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/criterion/Restrictions.cfc b/src/cfml/system/wirebox/system/orm/hibernate/criterion/Restrictions.cfc deleted file mode 100644 index e2087beab..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/criterion/Restrictions.cfc +++ /dev/null @@ -1,266 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** - -Author : Michael McKellip , Luis Majano -Description : - A proxy to hibernate org.hibernate.criterion.Restrictions object to allow - for criteria based querying -*/ -component singleton{ - - // Constructor - Restrictions function init(){ - restrictions = CreateObject("java","org.hibernate.criterion.Restrictions"); - return this; - } - - // Get the native hibernate restrictions object: org.hibernate.criterion.Restrictions - any function getNativeClass(){ - return restrictions; - } - - // Where the property value is between two distinct values - any function between(required string property, required any minValue, required any maxValue){ - return restrictions.between(arguments.property, arguments.minValue, arguments.maxValue); - } - - // Where a property equals a particular value, you can also use eq() - any function isEq(required string property, required any propertyValue){ - return restrictions.eq(arguments.property, arguments.propertyValue); - } - - // Where a property is true - any function isTrue(required string property){ - return restrictions.eq(arguments.property, javaCast("boolean",true) ); - } - - // Where a property is false - any function isFalse(required string property){ - return restrictions.eq(arguments.property, javaCast("boolean",false) ); - } - - // Where one property must equal another - any function eqProperty(required string property, required string otherProperty){ - return restrictions.eqProperty(arguments.property, arguments.otherProperty); - } - - // Where a property is greater than a particular value, you can also use gt() - any function isGt(required string property, required any propertyValue){ - return restrictions.gt(arguments.property, arguments.propertyValue); - } - - // Where a one property must be greater than another - any function gtProperty(required string property, required string otherProperty){ - return restrictions.gtProperty(arguments.property, arguments.otherProperty); - } - - // Where a property is greater than or equal to a particular value, you can also use ge() - any function isGe(required string property, required any propertyValue){ - return restrictions.ge(arguments.property, arguments.propertyValue); - } - - // Where a one property must be greater than or equal to another - any function geProperty(required string property, required string otherProperty){ - return restrictions.geProperty(arguments.property, arguments.otherProperty); - } - - // Where an objects id equals the specified value - any function idEQ(required any propertyValue){ - return restrictions.idEQ(arguments.propertyValue); - } - - // A case-insensitive 'like' expression - any function ilike(required string property, required string propertyValue){ - return restrictions.ilike(arguments.property, arguments.propertyValue); - } - - // Where a property is contained within the specified list of values, the property value can be a collection (struct) or array or list, you can also use in() - any function isIn(required string property, required any propertyValue){ - // infalte to array if simple values - if( isSimpleValue(arguments.propertyValue) ){ arguments.propertyValue = listToArray( arguments.propertyValue); } - return restrictions.in(arguments.property, arguments.propertyValue); - } - - // Where a collection property is empty - any function isEmpty(required string property){ - return restrictions.isEmpty(arguments.property); - } - - // Where a collection property is not empty - any function isNotEmpty(required string property){ - return restrictions.isNotEmpty(arguments.property); - } - - // Where a property is null - any function isNull(required string property){ - return restrictions.isNull(arguments.property); - } - - // Where a property is not null - any function isNotNull(required string property){ - return restrictions.isNotNull(arguments.property); - } - - // Where a property is less than a particular value, you can also use lt() - any function islt(required string property, required any propertyValue){ - return restrictions.lt(arguments.property, arguments.propertyValue); - } - - // Where a one property must be less than another - any function ltProperty(required string property, required string otherProperty){ - return restrictions.ltProperty(arguments.property, arguments.otherProperty); - } - - // Where a property is less than or equal a particular value, you can also use le() - any function isle(required string property, required any propertyValue){ - return restrictions.le(arguments.property, arguments.propertyValue); - } - - // Where a one property must be less than or equal to another - any function leProperty(required string property, required string otherProperty){ - return restrictions.leProperty(arguments.property, arguments.otherProperty); - } - - // Equivalent to SQL like expression - any function like(required string property, required string propertyValue){ - return restrictions.like(arguments.property, arguments.propertyValue); - } - - // Where a property does not equal a particular value - any function ne(required string property, required any propertyValue){ - return restrictions.ne(arguments.property, arguments.propertyValue); - } - - // Where one property does not equal another - any function neProperty(required string property, required any otherProperty){ - return restrictions.neProperty(arguments.property, arguments.otherProperty); - } - - // Where a collection property's size equals a particular value - any function sizeEq(required string property, required any propertyValue){ - return restrictions.sizeEq(arguments.property, arguments.propertyValue); - } - - // Where a collection property's size is greater than a particular value - any function sizeGT(required string property, required any propertyValue){ - return restrictions.sizeGT(arguments.property, arguments.propertyValue); - } - - // Where a collection property's size is greater than or equal a particular value - any function sizeGE(required string property, required any propertyValue){ - return restrictions.sizeGE(arguments.property, arguments.propertyValue); - } - - // Where a collection property's size is less than a particular value - any function sizeLT(required string property, required any propertyValue){ - return restrictions.sizeLT(arguments.property, arguments.propertyValue); - } - - // Where a collection property's size is less than or equal a particular value - any function sizeLE(required string property, required any propertyValue){ - return restrictions.sizeLE(arguments.property, arguments.propertyValue); - } - - // Where a collection property's size is not equal to a particular value - any function sizeNE(required string property, required any propertyValue){ - return restrictions.sizeNE(arguments.property, arguments.propertyValue); - } - - // Use arbitrary SQL to modify the resultset - any function sqlRestriction(required string sql){ - return restrictions.sqlRestriction(arguments.sql); - } - - // Group expressions together in a single conjunction (A and B and C...) and return the conjunction - any function conjunction(required array restrictionValues){ - var cj = restrictions.conjunction(); - - for(var i=1; i LTE ArrayLen(arguments.restrictionValues); i++){ - cj.add( arguments.restrictionValues[i] ); - } - - return cj; - } - - // Return the conjuction of N expressions as arguments - any function $and(){ - var expressions = []; - for(var key in arguments){ - arrayAppend(expressions, arguments[key]); - } - return this.conjunction(expressions); - } - - // Return the disjunction of N expressions as arguments - any function $or(){ - var expressions = []; - for(var key in arguments){ - arrayAppend(expressions, arguments[key]); - } - return this.disjunction(expressions); - } - - // Group expressions together in a single disjunction (A or B or C...) - any function disjunction(required array restrictionValues){ - var dj = restrictions.disjunction(); - - for(var i=1; i LTE ArrayLen(arguments.restrictionValues); i++){ - dj.add( arguments.restrictionValues[i] ); - } - - return dj; - } - - // Return the negation of an expression - any function isNot(required any criterion){ - return restrictions.not(arguments.criterion); - } - - any function onMissingMethod(required string missingMethodName, required struct missingMethodArguments){ - // build args to array - var args = []; - for(var i = 1; i <= structCount(arguments.missingMethodArguments); i++){ - ArrayAppend(args, "arguments.missingMethodArguments[#i#]"); - } - - switch(arguments.missingMethodName){ - case "eq": - return isEq(argumentCollection=arguments.missingMethodArguments); - break; - case "in": - return isIn(argumentCollection=arguments.missingMethodArguments); - break; - case "gt": - return isGt(argumentCollection=arguments.missingMethodArguments); - break; - case "lt": - return isLT(argumentCollection=arguments.missingMethodArguments); - break; - case "le": - return isLE(argumentCollection=arguments.missingMethodArguments); - break; - case "ge": - return isGe(argumentCollection=arguments.missingMethodArguments); - break; - case "and": - return $and(argumentCollection=arguments.missingMethodArguments); - break; - case "or": - return $or(argumentCollection=arguments.missingMethodArguments); - break; - case "not": - return isNot(argumentCollection=arguments.missingMethodArguments); - break; - default:{ - if( arrayLen(args) ){ - return evaluate("restrictions.#arguments.missingMethodName#(#arrayToList(args)#)"); - } - return evaluate("restrictions.#arguments.missingMethodName#()"); - } - } - - } -} diff --git a/src/cfml/system/wirebox/system/orm/hibernate/criterion/Subqueries.cfc b/src/cfml/system/wirebox/system/orm/hibernate/criterion/Subqueries.cfc deleted file mode 100644 index 690e7211c..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/criterion/Subqueries.cfc +++ /dev/null @@ -1,134 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** - -Description : - A proxy to hibernate org.hibernate.criterion.Subqueries object to allow - for criteria based subquerying -*/ -component singleton extends="wirebox.system.orm.hibernate.criterion.Restrictions"{ - - // Constructor - Subqueries function init( required criteria ) { - detachedCriteria = arguments.criteria; - subqueries = CreateObject( "java", "org.hibernate.criterion.Subqueries" ); - restrictions = CreateObject( "java", "org.hibernate.criterion.Restrictions" ); - return this; - } - // Get the native hibernate subqueries object: org.hibernate.criterion.Subqueries - any function getNativeClass(){ - return subqueries; - } - any function subEq( required any value ) { - return subqueries.eq( arguments.value, detachedCriteria ); - } - any function subEqAll( required any value ) { - return subqueries.eqAll( arguments.value, detachedCriteria ); - } - any function subGe( required any value ) { - return subqueries.ge( arguments.value, detachedCriteria ); - } - any function subGeAll( required any value ) { - return subqueries.geAll( arguments.value, detachedCriteria ); - } - any function subGeSome( required any value ) { - return subqueries.geSome( arguments.value, detachedCriteria ); - } - any function subGt( required any value ) { - return subqueries.gt( arguments.value, detachedCriteria ); - } - any function subGtAll( required any value ) { - return subqueries.gtAll( arguments.value, detachedCriteria ); - } - any function subGtSome( required any value ) { - return subqueries.gtSome( arguments.value, detachedCriteria ); - } - any function subIn( required any value ) { - return subqueries.in( arguments.value, detachedCriteria ); - } - any function subLe( required any value ) { - return subqueries.le( arguments.value, detachedCriteria ); - } - any function subLeAll( required any value ) { - return subqueries.leAll( arguments.value, detachedCriteria ); - } - any function subLeSome( required any value ) { - return subqueries.leSome( arguments.value, detachedCriteria ); - } - any function subLt( required any value ) { - return subqueries.lt( arguments.value, detachedCriteria ); - } - any function subLtAll( required any value ) { - return subqueries.ltAll( arguments.value, detachedCriteria ); - } - any function subLtSome( required any value ) { - return subqueries.ltSome( arguments.value, detachedCriteria ); - } - any function subNe( required any value ) { - return subqueries.ne( arguments.value, detachedCriteria ); - } - any function subNotIn( required any value ) { - return subqueries.notIn( arguments.value, detachedCriteria ); - } - // where subquery returns a result - any function exists() { - return subqueries.exists( detachedCriteria ); - } - // where subquery returns no result - any function notExists() { - return subqueries.notExists( detachedCriteria ); - } - any function propertyEq( required string property ){ - return subqueries.propertyEq( arguments.property, detachedCriteria ); - } - any function propertyEqAll( required string property ){ - return subqueries.propertyEqAll( arguments.property, detachedCriteria ); - } - any function propertyGe( required string property ){ - return subqueries.propertyGe( arguments.property, detachedCriteria ); - } - any function propertyGeAll( required string property ){ - return subqueries.propertyGeAll( arguments.property, detachedCriteria ); - } - any function propertyGeSome( required string property ){ - return subqueries.propertyGeSome( arguments.property, detachedCriteria ); - } - any function propertyGt( required string property ){ - return subqueries.propertyGt( arguments.property, detachedCriteria ); - } - any function propertyGtAll( required string property ){ - return subqueries.propertyGtAll( arguments.property, detachedCriteria ); - } - any function propertyGtSome( required string property ){ - return subqueries.propertyGtSome( arguments.property, detachedCriteria ); - } - any function propertyIn( required string property ){ - return subqueries.propertyIn( arguments.property, detachedCriteria ); - } - any function propertyLe( required string property ){ - return subqueries.propertyLe( arguments.property, detachedCriteria ); - } - any function propertyLeAll( required string property ){ - return subqueries.propertyLeAll( arguments.property, detachedCriteria ); - } - any function propertyLeSome( required string property ){ - return subqueries.propertyLeSome( arguments.property, detachedCriteria ); - } - any function propertyLt( required string property ){ - return subqueries.propertyLt( arguments.property, detachedCriteria ); - } - any function propertyLtAll( required string property ){ - return subqueries.propertyLtAll( arguments.property, detachedCriteria ); - } - any function propertyLtSome( required string property ){ - return subqueries.propertyLtSome( arguments.property, detachedCriteria ); - } - any function propertyNe( required string property ){ - return subqueries.propertyNe( arguments.property, detachedCriteria ); - } - any function propertyNotIn( required string property ){ - return subqueries.propertyNotIn( arguments.property, detachedCriteria ); - } -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/sql/SQLHelper.cfc b/src/cfml/system/wirebox/system/orm/hibernate/sql/SQLHelper.cfc deleted file mode 100644 index 92a20aa6b..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/sql/SQLHelper.cfc +++ /dev/null @@ -1,427 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** - -Description : - Simple utility for extracting SQL from native Criteria Query object -*/ -import org.hibernate.*; -component displayName="SQLHelper" accessors="true" { - - /** - * The log array - */ - property name="log" type="array"; - /** - * Format the SQL or not. - */ - property name="formatSql" type="boolean" default="false"; - /** - * Bit to return the executable SQL or not - */ - property name="returnExecutableSql" type="boolean" default="false"; - - /** - * Constructor - */ - SQLHelper function init( - required any criteriaBuilder, - boolean returnExecutableSql = false, - boolean formatSql = false - ){ - - // Setup properties - variables.cb = arguments.criteriaBuilder; - variables.entityName = cb.getEntityName(); - variables.criteriaImpl = cb.getNativeCriteria(); - variables.ormSession = criteriaImpl.getSession(); - variables.factory = ormSession.getFactory(); - // get formatter for sql string beautification - variables.formatter = createObject( "java", "org.hibernate.jdbc.util.BasicFormatterImpl" ); - // set properties - variables.log = []; - variables.formatSQL = arguments.formatSQL; - variables.returnExecutableSql = arguments.returnExecutableSql; - - return this; - } - - /** - * Logs current state of criteria to internal tracking log - * @label {string} The label for the log record - * return void - */ - function log( required string label="Criteria" ) { - var logentry = { - "type" = arguments.label, - "sql" = getSQL( argumentCollection=arguments ) - }; - arrayAppend( variables.log, logentry ); - - return this; - } - - /** - * Returns the SQL string that will be prepared for the criteria object at the time of request - * @returnExecutableSql {Boolean} Whether or not to do query param replacements on returned SQL string - * @formatSql {Boolean} Whether to format the sql - * return string - */ - string function getSQL( - required boolean returnExecutableSql=getReturnExecutableSql(), - required boolean formatSql=getFormatSql() - ){ - - var sql = getCriteriaJoinWalker().getSQLstring(); - var selection = getQueryParameters().getRowSelection(); - var useLimit = useLimit( selection ); - var hasFirstRow = getFirstRow( selection ) > 0; - var useOffset = hasFirstRow && useLimit && getDialect().supportsLimitOffset(); - - // try to add limit/offset in - if( useLimit ) { - sql = getDialect().getLimitstring( - sql, - useOffset ? getFirstRow(selection) : 0, - getMaxOrLimit( selection ) - ); - } - - // if we want executable sql string... - if( arguments.returnExecutableSql ) { - sql = replaceQueryParameters( sql, arguments.formatSql ); - } - - // if we want to beautify the sql string - if( arguments.formatSql ) { - sql = applyFormatting( sql ); - } - - return sql; - } - - /** - * Applies pretty formatting to a sql string - * @sql {string} The SQL string to format - * return string - */ - string function applyFormatting( required string sql ) { - return "" & formatter.format( arguments.sql ) & ""; - } - - /** - * Gets the positional SQL parameter values from the criteria query - * return array - */ - array function getPositionalSQLParameterValues() { - return getCriteriaQueryTranslator().getQueryParameters().getPositionalParameterValues(); - } - - /** - * Gets positional SQL parameter types from the criteria query - * @simple {Boolean} Whether to return a simply array or full objects - * return any - */ - any function getPositionalSQLParameterTypes( required Boolean simple=true ) { - var types = getCriteriaQueryTranslator().getQueryParameters().getPositionalParameterTypes(); - if( !arguments.simple ) { - return types; - } - var simplifiedTypes = []; - for( var x=1; x <= arrayLen( types ); x++ ) { - arrayAppend( simplifiedTypes, types[ x ].getName() ); - } - return simplifiedTypes; - } - - /** - * Returns a formatted array of parameter value and types - * return array - */ - public Array function getPositionalSQLParameters() { - var params = []; - var values = getPositionalSQLParameterValues(); - var types = getPositionalSQLParameterTypes( true ); - // loop over them - for( var x=1; x <= arrayLen( types ); x++ ) { - arrayAppend( params, { - "type" = types [ x ], - "value" = values[ x ] - }); - } - return params; - } - - /** - * Generates a unique SQL Alias within the criteria query - * return string - */ - string function generateSQLAlias() { - return getCriteriaQueryTranslator().generateSQLAlias(); - } - - /** - * Retrieves the "rooted" SQL alias for the criteria query - * return string - */ - string function getRootSQLAlias() { - return getCriteriaQueryTranslator().getRootSQLAlias(); - } - - /** - * Retrieves the projected types of the criteria query - * return string - */ - any function getProjectedTypes() { - return getCriteriaQueryTranslator().getProjectedTypes(); - } - - /** - * Get the alias of the current projection - * return string - */ - string function getProjectionAlias() { - return getCriteriaQueryTranslator().getProjectedAliases()[ 1 ]; - } - - /** - * Retrieves the correct dialect of the database engine - * return any - */ - any function getDialect() { - return factory.getDialect(); - } - - Boolean function canLogLimitOffset() { - var dialect = getDialect(); - var max = !isNull( criteriaImpl.getMaxResults() ) ? criteriaImpl.getMaxResults() : 0; - return dialect.supportsLimitOffset() && max > 0; - } - - /********************************* PRIVATE *********************************/ - - /** - * Small utility method to convert weird arrays from Java methods into something CF understands - * @array {Array} The array to convert - * return Array - */ - private array function convertToCFArray( required any array ) { - var newArray = []; - newArray.addAll( createObject( "java", "java.util.Arrays" ).asList( arguments.array ) ); - return newArray; - } - - /** - * Gets currently applied query parameters for the query object - * return org.hibernate.engine.QueryParameters - */ - private any function getQueryParameters() { - var translator = getCriteriaQueryTranslator(); - return translator.getQueryParameters(); - } - - /** - * replace query parameter placeholders with their actual values (for detachedSQLProjection) - * @sql (string) The sql string to massage - * returns string - */ - private string function replaceQueryParameters( required string sql ) { - var dialect = getDialect(); - var parameters = getQueryParameters(); - // get parameter values and types - var values = parameters.getPositionalParameterValues(); - var types = parameters.getPositionalParameterTypes(); - // get query so we can see full number of ordinal parameters - var query = ormsession.createSQLQuery( sql ); - var meta = query.getParameterMetaData(); - var positionalParameterCount = meta.getOrdinalParameterCount(); - // get row selection - var selection = parameters.getRowSelection(); - // prepare some meta about the limit info...need to handle this separately - var useLimit = useLimit( selection ); - var firstRow = dialect.convertToFirstRowValue( getFirstRow( selection ) ); - var hasFirstRow = dialect.supportsLimitOffset() && ( firstRow > 0 || dialect.forceLimitUsage() ); - var useOffset = hasFirstRow && useLimit && dialect.supportsLimitOffset(); - var reverse = dialect.bindLimitParametersInReverseOrder(); - /** - APPROACH: - Unfortunately, there does not seem to be any really good way to retrieve the SQL that will be executed, - since it isn't actually sent to the db engine as executable SQL - So, we have to rely upon the QueryTranslator to provide us details about positional paramters that are going to be sent - However, the "limit/offset" data isn't handled by the Translator, so we also need to spin up a regular SQL Query to determine - how many total ordinal parameters are getting sent with the query string. - - This, combined with info that Hibernate knows about each db dialect, we can smartly fill in the gaps for the "limit/offset" - information, as well as fill in the ordinal parameters values and return a SQL string that is as close to the actual string - that will be executed on the db as possible. - - So the actual idea is to take the ordinal parameter values and types which QueryTranslator knows about, and intelligently add to - those lists based on the dialect of the database engine. - */ - // if we have positional parameters - if( positionalParameterCount ) { - var positionalValues = convertToCFArray( values ); - var positionalTypes = convertToCFArray( types ); - // if our query at this point in time is using "limit/offset" - if( useLimit ) { - // we'll reuse this - var integerType = createObject( "java", "org.hibernate.type.IntegerType" ); - // Ex: Engines like SQL Server put limits first - if( dialect.bindLimitParametersFirst() ) { - positionalValues = bindLimitParameters( positionalValues, false, selection ); - // add for max/limit - arrayInsertAt( positionalTypes, 1, integerType ); - if( hasFirstRow ) { - arrayInsertAt( positionalTypes, 1, integerType ); - } - } - // Ex: Engines like MySQL put limits last - else { - positionalValues = bindLimitParameters( positionalValues, true, selection ); - // append for max/limit - arrayAppend( positionalTypes, integerType ); - if( hasFirstRow ) { - arrayAppend( positionalTypes, integerType ); - } - } - } - // loop over parameters; need to replace those pesky "?" with the real values - for( var x=1; x<=arrayLen( positionalTypes ); x++ ) { - var type = positionalTypes[ x ]; - var value = positionalValues[ x ]; - // cast values to appropriate SQL type - if( !type.isAssociationType() && type.getName() != "text" ) { - var pvTyped = type.objectToSQLstring( value, getDialect() ); - // remove parameter placeholders - arguments.sql = reReplaceNoCase( arguments.sql, "\?", pvTyped, "one" ); - } - else if( type.getName() == "text" ) { - // remove parameter placeholders - arguments.sql = reReplaceNoCase( arguments.sql, "\?", "'#value#'", "one" ); - } - // association values can't be cast to SQL string by normal convention; just do a simple replace - else { - arguments.sql = reReplaceNoCase( arguments.sql, "\?", value, "one" ); - } - } - // for some reason, JoinWalker doesn't sync up root paramters with the generated alias...so fix those - arguments.sql = reReplaceNoCase( arguments.sql, "this\.", "this_.", "all" ); - } - return arguments.sql; - } - - /** - * Inserts parameter values into the running list based on the dialect of the database engine - * @positionalValues {Array} The positional values for this query - * @append {Boolean} Whether values are appended or prepended to the array - * @selection {any} The current row selection - * return Array - */ - private Array function bindLimitParameters( required Array positionalValues, required Boolean append, required any selection ) { - var dialect = getDialect(); - // trackers - var newPositionalValues = []; - var finalArray = []; - // prepare some meta about the limit info - var firstRow = dialect.convertToFirstRowValue( getFirstRow( selection ) ); - var lastRow = getMaxOrLimit( selection ); - var hasFirstRow = dialect.supportsLimitOffset() && ( firstRow > 0 || dialect.forceLimitUsage() ); - var reverse = dialect.bindLimitParametersInReverseOrder(); - // has offset...need to add both limit and offset - if ( hasFirstRow ) { - // if offset/limit are reversed - // EX: Other engines "reverse" this and use: LIMIT {limit}, {offset} - if( reverse ) { - arrayAppend( newPositionalValues, selection.getMaxRows() ); - arrayAppend( newPositionalValues, firstRow ); - } - // EX: In MySQL, offset limit are: LIMIT {offset}, {limit} - else { - arrayAppend( newPositionalValues, firstRow ); - arrayAppend( newPositionalValues, selection.getMaxRows() ); - } - } - // no start row...just add regular limit - else { - arrayAppend( newPositionalValues, selection.getMaxRows() ); - } - // APPEND: Engines like MySQL, etc. put limit/offset at the end of the statement - if( append ) { - positionalValues.addAll( newPositionalValues ); - return positionalValues; - } - // PREPEND:Engines like SQL Server, etc. use top/row numbering - else { - newPositionalValues.addAll( positionalValues ); - return newPositionalValues; - } - } - - /** - * Determines whether the database engine allows for the use of "limit/offset" syntax - * @selection {any} The current row selection - * return Boolean - */ - private Boolean function useLimit( required any selection ) { - return getDialect().supportsLimit() && hasMaxRows( argumentCollection=arguments ); - } - - /** - * Determines whether the current row selection has a limit already applied - * @selection {any} The current row selection - * return Boolean - */ - private Boolean function hasMaxRows( required any selection ) { - return !isNull( selection.getMaxRows() ); - } - - /** - * Gets the first row (or 0) for the current row selection - * @selection {any} The current row selection - * return Numeric - */ - private Numeric function getFirstRow( required any selection ) { - return isNull( selection.getFirstRow() ) ? 0 : selection.getFirstRow().intValue(); - } - - /** - * Gets correct "limit" value for the current row selection - * @selection {any} The current row selection - * return Numeric - */ - private Numeric function getMaxOrLimit( required any selection ) { - var dialect = getDialect(); - var firstRow = dialect.convertToFirstRowValue( getFirstRow( selection ) ); - var lastRow = selection.getMaxRows().intValue(); - return dialect.useMaxForLimit() ? lastRow+firstRow : lastRow; - } - - /** gets an instance of CriteriaJoinWalker, which can allow for translating criteria query into a sql string - * returns CriteriaJoinWalker - */ - private any function getCriteriaJoinWalker() { - // not nearly as cool as the walking dead kind, but is still handy for turning a criteria into a sql string ;) - return createObject( "java", "org.hibernate.loader.criteria.CriteriaJoinWalker" ).init( - factory.getEntityPersister( entityName ), // persister (loadable) - getCriteriaQueryTranslator(), // translator - factory, // factory - criteriaImpl, // criteria - entityName, // rootEntityName - ormSession.getLoadQueryInfluencers() // loadQueryInfluencers - ); - } - /** gets an instance of CriteriaQueryTranslator, which can prepares criteria query for conversion to SQL - * returns CriteriaQueryTranslator - */ - private any function getCriteriaQueryTranslator() { - // create new criteria query translator; we'll use this to build up the query string - return createObject( "java", "org.hibernate.loader.criteria.CriteriaQueryTranslator" ).init( - factory, // factory - criteriaImpl, // criteria - entityName, // rootEntityName - criteriaImpl.getAlias() // rootSQLAlias - ); - } -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/util/CFORMUtil.cfc b/src/cfml/system/wirebox/system/orm/hibernate/util/CFORMUtil.cfc deleted file mode 100644 index 8d67202dc..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/util/CFORMUtil.cfc +++ /dev/null @@ -1,97 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Luis Majano & Mike McKellip -Description : - -This implementation supports multiple DSNs for ORM a-la Adobe ColdFusion 9 - ------------------------------------------------------------------------> -*/ -component implements="wirebox.system.orm.hibernate.util.IORMUtil"{ - - public void function flush(string datasource) { - if(StructKeyExists(arguments,"datasource")) - ORMFlush(arguments.datasource); - else - ORMFlush(); - } - - public any function getSession(string datasource) { - if(StructKeyExists(arguments,"datasource")) - // get actual session from coldfusion.orm.hibernate.SessionWrapper - return ORMGetSession(arguments.datasource).getActualSession(); - else - // get actual session from coldfusion.orm.hibernate.SessionWrapper - return ORMGetSession().getActualSession(); - } - - public any function getSessionFactory(string datasource) { - if(StructKeyExists(arguments,"datasource")) - return ORMGetSessionFactory(arguments.datasource); - else - return ORMGetSessionFactory(); - } - - public void function clearSession(string datasource) { - if(StructKeyExists(arguments,"datasource")) - ORMClearSession(arguments.datasource); - else - ORMClearSession(); - } - - public void function closeSession(string datasource) { - if(StructKeyExists(arguments,"datasource")) - ORMCloseSession(arguments.datasource); - else - ORMCloseSession(); - } - - public void function evictQueries(string cachename, string datasource) { - if(StructKeyExists(arguments,"cachename") AND StructKeyExists(arguments,"datasource")) - ORMEvictQueries(arguments.cachename, arguments.datasource); - else if(StructKeyExists(arguments,"cachename")) - ORMEvictQueries(arguments.cachename); - else - ORMEvictQueries(); - } - - /** - * Returns the datasource for a given entity - * @entity The entity reference. Can be passed as an object or as the entity name. - */ - public string function getEntityDatasource(required entity) { - // DEFAULT datasource - var datasource = getDefaultDatasource(); - - if(!IsObject(arguments.entity)) arguments.entity= EntityNew(arguments.entity); - - var md = getMetaData(arguments.entity); - if( StructKeyExists(md,"DATASOURCE") ) datasource = md.DATASOURCE; - - return datasource; - } - - /** - * Get the default application datasource - */ - public string function getDefaultDatasource(){ - // get application metadata - if( listFirst(server.coldfusion.productVersion,",") gte 10 ){ - var settings = getApplicationMetadata(); - } - else{ - var settings = application.getApplicationSettings(); - } - - // check orm settings first - if( structKeyExists( settings,"ormsettings") AND structKeyExists(settings.ormsettings,"datasource")){ - return settings.ormsettings.datasource; - } - // else default to app datasource - return settings.datasource; - }; - -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/util/IORMUtil.cfc b/src/cfml/system/wirebox/system/orm/hibernate/util/IORMUtil.cfc deleted file mode 100644 index fe26a8a31..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/util/IORMUtil.cfc +++ /dev/null @@ -1,25 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Luis Majano & Mike McKellip -Description : - -The base interface for retreieveing the right CF ORM session for CFML engines -that do not support multiple dsn's yet. - -Once they do, these implementations will disappear. - ------------------------------------------------------------------------> -*/ -interface { - public void function flush(string datasource); - public any function getSession(string datasource); - public any function getSessionFactory(string datasource); - public void function clearSession(string datasource); - public void function closeSession(string datasource); - public void function evictQueries(string cachename, string datasource); - public string function getEntityDatasource(required entity); - public string function getDefaultDatasource(); -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtil.cfc b/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtil.cfc deleted file mode 100644 index 80f0eccb8..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtil.cfc +++ /dev/null @@ -1,63 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Luis Majano & Mike McKellip -Description : - -This ORM utility implementation is for engines that do NOT support multiple dsn's - ------------------------------------------------------------------------> -*/ -component implements="wirebox.system.orm.hibernate.util.IORMUtil"{ - - public void function flush(string datasource) { - ORMFlush(); - } - - public any function getSession(string datasource) { - return ORMGetSession(); - } - - public any function getSessionFactory(string datasource) { - return ORMGetSessionFactory(); - } - - public void function clearSession(string datasource) { - ORMClearSession(); - } - - public void function closeSession(string datasource) { - ORMCloseSession(); - } - - public void function evictQueries(string cachename, string datasource) { - if(StructKeyExists(arguments,"cachename")) - ORMEvictQueries(arguments.cachename); - else - ORMEvictQueries(); - } - - /** - * Returns the datasource for a given entity - * @entity The entity reference. Can be passed as an object or as the entity name. - */ - public string function getEntityDatasource(required entity) { - return getDefaultDatasource(); - } - - /** - * Get the default application datasource - */ - public string function getDefaultDatasource(){ - var settings = application.getApplicationSettings(); - // check orm settings first - if( structKeyExists( settings,"ormsettings") AND structKeyExists(settings.ormsettings,"datasource")){ - return settings.ormsettings.datasource; - } - // else default to app datasource - return settings.datasource; - }; - -} \ No newline at end of file diff --git a/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtilFactory.cfc b/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtilFactory.cfc deleted file mode 100644 index 423c495dd..000000000 --- a/src/cfml/system/wirebox/system/orm/hibernate/util/ORMUtilFactory.cfc +++ /dev/null @@ -1,31 +0,0 @@ -/** -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -Author : Luis Majano & Mike McKellip -Description : - -A simple factory to return the right ORM utility according to CFML engine - ------------------------------------------------------------------------> -*/ -import wirebox.system.orm.hibernate.util.*; - -component{ - - public any function getORMUtil() { - switch( getPlatform() ) { - case "ColdFusion Server": - return new CFORMUtil(); - break; - default: - return new ORMUtil(); - } - } - - private string function getPlatform() { - return server.coldfusion.productname; - } - -} \ No newline at end of file diff --git a/src/cfml/templates/cpu.json b/src/cfml/templates/cpu.json deleted file mode 100644 index 1f7beda3e..000000000 --- a/src/cfml/templates/cpu.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "projectURL" : "http://localhost", - "testbox" : { - "runnerURL" : "http://localhost", - "browserURL" : "http://localhost" - } -} \ No newline at end of file diff --git a/src/cfml/userconfig/commandbox.json b/src/cfml/userconfig/commandbox.json deleted file mode 100644 index 4eb7c3f98..000000000 --- a/src/cfml/userconfig/commandbox.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/src/cfml/userconfig/readme.txt b/src/cfml/userconfig/readme.txt deleted file mode 100644 index ee83d88de..000000000 --- a/src/cfml/userconfig/readme.txt +++ /dev/null @@ -1,16 +0,0 @@ - _____ _ ____ - / ____| | | _ \ - | | ___ _ __ ___ _ __ ___ __ _ _ __ __| | |_) | _____ __ - | | / _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` | _ < / _ \ \/ / - | |___| (_) | | | | | | | | | | | (_| | | | | (_| | |_) | (_) > < - \_____\___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|____/ \___/_/\_\ -******************************************************************************** -Copyright Since 2005 ColdBox Framework by Luis Majano and Ortus Solutions, Corp -www.coldbox.org | www.luismajano.com | www.ortussolutions.com -******************************************************************************** -COMMANDBOX.JSON HELP -******************************************************************************** -The commandbox.json is your user preferences file you can tweak to alter the -behavior of CommandBox. Below is a description of what the settings can do: - - diff --git a/src/java/com/ortussolutions/commandbox/authentication/ProxyAuthenticator.java b/src/java/com/ortussolutions/commandbox/authentication/ProxyAuthenticator.java new file mode 100644 index 000000000..4ae9b7fff --- /dev/null +++ b/src/java/com/ortussolutions/commandbox/authentication/ProxyAuthenticator.java @@ -0,0 +1,27 @@ +/** +********************************************************************************* +* Copyright Since 2014 CommandBox by Ortus Solutions, Corp +* www.coldbox.org | www.ortussolutions.com +******************************************************************************** +* @author Brad Wood, Luis Majano +* +* I implement proxy authentication +*/ +package com.ortussolutions.commandbox.authentication; + +import java.net.Authenticator; +import java.net.PasswordAuthentication; + +public class ProxyAuthenticator extends Authenticator { + + private String user, password; + + public ProxyAuthenticator(String user, String password) { + this.user = user; + this.password = password; + } + + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(user, password.toCharArray()); + } +} diff --git a/tests/cfml/commands/TestHelp.cfc b/tests/cfml/commands/TestHelp.cfc index bc6505db5..7c709b551 100644 --- a/tests/cfml/commands/TestHelp.cfc +++ b/tests/cfml/commands/TestHelp.cfc @@ -2,7 +2,7 @@ component name="TestHelp" extends="mxunit.framework.TestCase" { public void function testCommandService() { shell = application.wirebox.getInstance( 'Shell' ); - helpCommand = application.wirebox.getInstance( 'commandbox.system.commands.help' ); + // helpCommand = application.wirebox.getInstance( 'commandbox.system.commands.help' ); }