/// <summary>
        /// Gets the HQL for debugging purposes only.
        /// </summary>
        /// <param name="procedureStepClasses"></param>
        /// <param name="criteria"></param>
        /// <param name="projection"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        public string GetWorklistItemsHql(Type[] procedureStepClasses, WorklistItemSearchCriteria[] criteria, WorklistItemProjection projection, SearchResultPage page)
        {
            var args  = new QueryBuilderArgs(procedureStepClasses, criteria, projection, page);
            var query = BuildWorklistQuery(args);

            return(query.Hql);
        }
        /// <summary>
        /// Builds a worklist item query, including the ordering and paging directives.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private HqlProjectionQuery BuildWorklistQuery(QueryBuilderArgs args)
        {
            var query = new HqlProjectionQuery();

            this.WorklistItemQueryBuilder.AddRootQuery(query, args);
            this.WorklistItemQueryBuilder.AddConstrainPatientProfile(query, args);
            this.WorklistItemQueryBuilder.AddCriteria(query, args);

            if (args is WorklistQueryArgs)
            {
                this.WorklistItemQueryBuilder.AddFilters(query, (WorklistQueryArgs)args);
            }

            if (args.CountQuery)
            {
                this.WorklistItemQueryBuilder.AddCountProjection(query, args);
            }
            else
            {
                this.WorklistItemQueryBuilder.AddOrdering(query, args);
                this.WorklistItemQueryBuilder.AddItemProjection(query, args);
                this.WorklistItemQueryBuilder.AddPagingRestriction(query, args);
            }

            return(query);
        }
        /// <summary>
        /// Gets the set of items matching the specified criteria, returned as tuples shaped by the specified projection.
        /// </summary>
        public IList <object[]> GetWorklistItems(Type[] procedureStepClasses, WorklistItemSearchCriteria[] criteria, WorklistItemProjection projection, SearchResultPage page)
        {
            var args  = new QueryBuilderArgs(procedureStepClasses, criteria, projection, page);
            var query = BuildWorklistQuery(args);

            return(CollectionUtils.Map(ExecuteHql <object[]>(query), (object[] tuple) => this.WorklistItemQueryBuilder.PreProcessResult(tuple, args)));
        }
        /// <summary>
        /// Builds a query that searches for patient items.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        private HqlProjectionQuery BuildPatientSearchQuery(QueryBuilderArgs args)
        {
            var query = new HqlProjectionQuery();

            _patientQueryBuilder.AddRootQuery(query, null);
            _patientQueryBuilder.AddCriteria(query, args);

            if (args.CountQuery)
            {
                _patientQueryBuilder.AddCountProjection(query, args);
            }
            else
            {
                _patientQueryBuilder.AddItemProjection(query, args);
            }
            return(query);
        }
        /// <summary>
        /// Builds a query that searches for worklist items.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        protected HqlProjectionQuery BuildWorklistSearchQuery(QueryBuilderArgs args)
        {
            var query = new HqlProjectionQuery();

            this.WorklistItemQueryBuilder.AddRootQuery(query, args);
            this.WorklistItemQueryBuilder.AddConstrainPatientProfile(query, args);
            this.WorklistItemQueryBuilder.AddCriteria(query, args);
            this.WorklistItemQueryBuilder.AddActiveProcedureStepConstraint(query, args);

            if (args.CountQuery)
            {
                this.WorklistItemQueryBuilder.AddCountProjection(query, args);
            }
            else
            {
                this.WorklistItemQueryBuilder.AddItemProjection(query, args);
            }

            return(query);
        }
        /// <summary>
        /// Executes the specified query, using the specified query-builder to pre-process the results.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="worklistItemClass"></param>
        /// <param name="queryBuilder"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        protected IList <WorklistItem> DoQuery(HqlQuery query, Type worklistItemClass, IQueryBuilder queryBuilder, QueryBuilderArgs args)
        {
            // execute query
            var tuples = ExecuteHql <object[]>(query);

            // create a dummy worklist item, so we can get the tuple mapping exactly once, outside of the loop
            var tupleMapping = ((WorklistItem)Activator.CreateInstance(worklistItemClass)).GetTupleMapping(args.Projection);

            // use tuple mapping to create worklist items
            return(CollectionUtils.Map(tuples,
                                       (object[] tuple) => CreateWorklistItem(worklistItemClass, queryBuilder.PreProcessResult(tuple, args), tupleMapping)));
        }
        /// <summary>
        /// Executes the specified query, using the specified query-builder to pre-process the results.
        /// </summary>
        /// <typeparam name="TItem">Class of worklist item that will hold the results.</typeparam>
        /// <param name="query"></param>
        /// <param name="queryBuilder"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        protected List <TItem> DoQuery <TItem>(HqlQuery query, IQueryBuilder queryBuilder, QueryBuilderArgs args)
            where TItem : WorklistItem
        {
            var results = DoQuery(query, typeof(TItem), queryBuilder, args);

            return(CollectionUtils.Map(results, (WorklistItem r) => (TItem)r));
        }