001    /**
002     * Copyright 2004-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.hr.time.roles.dao;
017    
018    import java.sql.Date;
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.List;
022    
023    import org.apache.commons.collections.CollectionUtils;
024    import org.apache.commons.lang.StringUtils;
025    import org.apache.ojb.broker.query.Criteria;
026    import org.apache.ojb.broker.query.Query;
027    import org.apache.ojb.broker.query.QueryFactory;
028    import org.apache.ojb.broker.query.ReportQueryByCriteria;
029    import org.kuali.hr.job.Job;
030    import org.kuali.hr.time.roles.TkRole;
031    import org.kuali.hr.time.service.base.TkServiceLocator;
032    import org.kuali.hr.time.util.TKUtils;
033    import org.kuali.hr.time.util.TkConstants;
034    import org.kuali.hr.time.workarea.WorkArea;
035    import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb;
036    import org.kuali.rice.krad.service.KRADServiceLocator;
037    
038    public class TkRoleDaoSpringOjbImpl extends PlatformAwareDaoBaseOjb implements TkRoleDao {
039    
040        public List<TkRole> findAllRoles(String principalId, Date asOfDate) {
041            return findRoles(principalId, asOfDate, null, null, null, null);
042        }
043    
044        @SuppressWarnings("unchecked")
045        @Override
046        public List<TkRole> findPositionRoles(String positionNumber, Date asOfDate, String roleName, Long workArea, String department, String chart) {
047            List<TkRole> roles = new ArrayList<TkRole>();
048    
049            Criteria root = new Criteria();
050            Criteria effdt = new Criteria();
051            Criteria timestamp = new Criteria();
052            ReportQueryByCriteria effdtSubQuery;
053            ReportQueryByCriteria timestampSubQuery;
054    
055            effdt.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
056            effdt.addEqualToField("positionNumber", Criteria.PARENT_QUERY_PREFIX + "positionNumber");
057            effdt.addLessOrEqualThan("effectiveDate", asOfDate);
058    
059            // EFFECTIVE DATE --
060    
061            // Adding criteria to nest an AND that has multiple ORs to select
062            // the correct ID / date combination.
063            Criteria orWrapperEd = new Criteria();
064            Criteria nstWaEd = new Criteria();
065            Criteria nstDptEd = new Criteria();
066            Criteria nstChrEd = new Criteria();
067    
068            // Inner AND to allow for all null chart/dept/work area
069            Criteria nullAndWrapper = new Criteria();
070            nullAndWrapper.addIsNull("workArea");
071            nullAndWrapper.addIsNull("department");
072            nullAndWrapper.addIsNull("chart");
073    
074            nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
075            nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
076            nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
077            orWrapperEd.addOrCriteria(nstWaEd);
078            orWrapperEd.addOrCriteria(nstDptEd);
079            orWrapperEd.addOrCriteria(nstChrEd);
080    
081            // Inner AND to allow for all null chart/dept/work area
082            orWrapperEd.addOrCriteria(nullAndWrapper);
083    
084            // Add the inner OR criteria to effective date
085            effdt.addAndCriteria(orWrapperEd);
086    
087            effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
088            effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
089    
090    
091            // TIMESTAMP --
092    
093            //Configure the actual "criteria" in the where clause
094            timestamp.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
095            timestamp.addEqualToField("positionNumber", Criteria.PARENT_QUERY_PREFIX + "positionNumber");
096            timestamp.addEqualToField("effectiveDate", Criteria.PARENT_QUERY_PREFIX + "effectiveDate");
097    
098            // Adding criteria to nest an AND that has multiple ORs to select
099            // the correct ID / date combination.
100            orWrapperEd = new Criteria();
101            nstWaEd = new Criteria();
102            nstDptEd = new Criteria();
103            nstChrEd = new Criteria();
104    
105            // Inner AND to allow for all null chart/dept/work area
106            nullAndWrapper = new Criteria();
107            nullAndWrapper.addIsNull("workArea");
108            nullAndWrapper.addIsNull("department");
109            nullAndWrapper.addIsNull("chart");
110    
111            nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
112            nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
113            nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
114            orWrapperEd.addOrCriteria(nstWaEd);
115            orWrapperEd.addOrCriteria(nstDptEd);
116            orWrapperEd.addOrCriteria(nstChrEd);
117    
118            // Inner AND to allow for all null chart/dept/work area
119            orWrapperEd.addOrCriteria(nullAndWrapper);
120    
121            // Add the inner OR criteria to effective date
122            timestamp.addAndCriteria(orWrapperEd);
123    
124            timestampSubQuery = QueryFactory.newReportQuery(TkRole.class, timestamp);
125            timestampSubQuery.setAttributes(new String[]{"max(timestamp)"});
126    
127    
128            // Filter by Max(EffDt) / Max(Timestamp)
129            root.addEqualTo("effectiveDate", effdtSubQuery);
130            root.addEqualTo("timestamp", timestampSubQuery);
131    
132            // Optional ROOT criteria added :
133            if (workArea != null)
134                root.addEqualTo("workArea", workArea);
135            if (StringUtils.isNotEmpty(department))
136                root.addEqualTo("department", department);
137            if (chart != null)
138                root.addEqualTo("chart", chart);
139            if (roleName != null)
140                root.addEqualTo("roleName", roleName);
141            if (positionNumber != null)
142                root.addEqualTo("positionNumber", positionNumber);
143    
144            // Filter for ACTIVE = 'Y'
145            Criteria activeFilter = new Criteria();
146            activeFilter.addEqualTo("active", true);
147            root.addAndCriteria(activeFilter);
148    
149            Query query = QueryFactory.newQuery(TkRole.class, root);
150            Collection c = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
151    
152            if (c != null) {
153                roles.addAll(c);
154            }
155    
156            return roles;
157        }
158    
159        @SuppressWarnings("unchecked")
160        @Override
161        public List<TkRole> findRoles(String principalId, Date asOfDate, String roleName, Long workArea, String department, String chart) {
162            List<TkRole> roles = new ArrayList<TkRole>();
163    
164            Criteria root = new Criteria();
165    
166            if (StringUtils.isNotEmpty(principalId)) {
167                root.addEqualTo("principalId", principalId);
168            }
169    
170            if (asOfDate != null) {
171                    Criteria effdt = new Criteria();
172                    effdt.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
173                    effdt.addEqualToField("principalId", Criteria.PARENT_QUERY_PREFIX + "principalId");
174                    effdt.addLessOrEqualThan("effectiveDate", asOfDate);
175                    if (workArea != null || StringUtils.isNotEmpty(department) || StringUtils.isNotEmpty(chart)) {
176                        if (workArea != null)
177                            effdt.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea");
178                        if (department != null)
179                            effdt.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department");
180                        if (chart != null)
181                            effdt.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart");
182                    }
183            
184                Criteria timestamp = new Criteria();
185                    timestamp.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
186                    timestamp.addEqualToField("principalId", Criteria.PARENT_QUERY_PREFIX + "principalId");
187                    timestamp.addEqualToField("effectiveDate", Criteria.PARENT_QUERY_PREFIX + "effectiveDate");
188                    if (workArea != null || StringUtils.isNotEmpty(department) || StringUtils.isNotEmpty(chart)) {
189                        if (workArea != null)
190                            timestamp.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea");
191                        if (department != null)
192                            timestamp.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department");
193                        if (chart != null)
194                            timestamp.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart");
195                    }
196            
197                    ReportQueryByCriteria timestampSubQuery;
198                    timestampSubQuery = QueryFactory.newReportQuery(TkRole.class, timestamp);
199                    timestampSubQuery.setAttributes(new String[]{"max(timestamp)"});
200            
201                    effdt.addEqualTo("timestamp", timestampSubQuery);
202            
203                    ReportQueryByCriteria effdtSubQuery;
204                    effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
205                    effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
206            
207                    root.addEqualTo("effectiveDate", effdtSubQuery);
208            }
209            
210            if (StringUtils.isNotEmpty(roleName)) {
211                root.addEqualTo("roleName", roleName);
212            }
213            
214            if (workArea != null) {
215                root.addEqualTo("workArea", workArea);
216            }
217    
218            if (StringUtils.isNotEmpty(department)) {
219                Criteria departmentCriteria = new Criteria();
220                departmentCriteria.addEqualTo("department", department);
221                Collection<WorkArea> collectionWorkAreas = TkServiceLocator.getWorkAreaService().getWorkAreas(department, asOfDate);
222                if (CollectionUtils.isNotEmpty(collectionWorkAreas)) {
223                    List<Long> longWorkAreas = new ArrayList<Long>();
224                    for(WorkArea cwa : collectionWorkAreas){
225                        longWorkAreas.add(cwa.getWorkArea());
226                    }
227                    Criteria workAreaCriteria = new Criteria();
228                    workAreaCriteria.addIn("workArea", longWorkAreas);
229                    departmentCriteria.addOrCriteria(workAreaCriteria);
230                }
231                root.addAndCriteria(departmentCriteria);
232            }
233            
234            if (StringUtils.isNotEmpty(chart)) {
235                root.addEqualTo("chart", chart);
236            }
237    
238            root.addEqualTo("active", true);
239    
240            Query query = QueryFactory.newQuery(TkRole.class, root);
241            // limit the number of the resultset
242            // TODO: hard coding the limits?  probably not the most user friendly of ways to do this
243            query.setStartAtIndex(0);
244            query.setEndAtIndex(299);
245            Collection c = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
246    
247            if (c != null) {
248                roles.addAll(c);
249            }
250    
251            if (StringUtils.isNotBlank(principalId)) {
252                //Fetch all the jobs and grab any position roles for this persons jobs
253                List<Job> lstActiveJobs = TkServiceLocator.getJobService().getJobs(principalId, asOfDate);
254                for (Job job : lstActiveJobs) {
255                    if (job.getPositionNumber() != null) {
256                        List<TkRole> lstRoles = findPositionRoles(job.getPositionNumber(),
257                                asOfDate, roleName, workArea, department, chart);
258                        roles.addAll(lstRoles);
259                    }
260                }
261            } else if (workArea != null) {
262                List<TkRole> lstPosRoles = getPositionRolesForWorkArea(workArea, asOfDate);
263                for (TkRole tkRole : lstPosRoles) {
264                    roles.add(tkRole);
265                }
266            }
267            return roles;
268        }
269    
270        @SuppressWarnings("unchecked")
271        @Override
272        public List<TkRole> findInActiveRoles(String principalId, Date asOfDate, String roleName, Long workArea, String department, String chart) {
273            List<TkRole> roles = new ArrayList<TkRole>();
274    
275            Criteria root = new Criteria();
276            
277            if (StringUtils.isNotEmpty(principalId)) {
278                root.addEqualTo("principalId", principalId);
279            }
280    
281            if (asOfDate != null) {
282                Criteria effdt = new Criteria();
283                Criteria timestamp = new Criteria();
284                ReportQueryByCriteria effdtSubQuery;
285                ReportQueryByCriteria timestampSubQuery;
286    
287                    effdt.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
288                    effdt.addEqualToField("principalId", Criteria.PARENT_QUERY_PREFIX + "principalId");
289                    effdt.addLessOrEqualThan("effectiveDate", asOfDate);
290            
291                    // EFFECTIVE DATE --
292            
293                    // Adding criteria to nest an AND that has multiple ORs to select
294                    // the correct ID / date combination.
295                    Criteria orWrapperEd = new Criteria();
296                    Criteria nstWaEd = new Criteria();
297                    Criteria nstDptEd = new Criteria();
298                    Criteria nstChrEd = new Criteria();
299            
300                    // Inner AND to allow for all null chart/dept/work area
301                    Criteria nullAndWrapper = new Criteria();
302                    nullAndWrapper.addIsNull("workArea");
303                    nullAndWrapper.addIsNull("department");
304                    nullAndWrapper.addIsNull("chart");
305            
306                    nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
307                    nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
308                    nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
309                    orWrapperEd.addOrCriteria(nstWaEd);
310                    orWrapperEd.addOrCriteria(nstDptEd);
311                    orWrapperEd.addOrCriteria(nstChrEd);
312            
313                    // Inner AND to allow for all null chart/dept/work area
314                    orWrapperEd.addOrCriteria(nullAndWrapper);
315            
316                    // Add the inner OR criteria to effective date
317                    effdt.addAndCriteria(orWrapperEd);
318            
319                    effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
320                    effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
321            
322            
323                    // TIMESTAMP --
324            
325                    //Configure the actual "criteria" in the where clause
326                    timestamp.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
327                    timestamp.addEqualToField("principalId", Criteria.PARENT_QUERY_PREFIX + "principalId");
328                    timestamp.addEqualToField("effectiveDate", Criteria.PARENT_QUERY_PREFIX + "effectiveDate");
329            
330                    // Adding criteria to nest an AND that has multiple ORs to select
331                    // the correct ID / date combination.
332                    orWrapperEd = new Criteria();
333                    nstWaEd = new Criteria();
334                    nstDptEd = new Criteria();
335                    nstChrEd = new Criteria();
336            
337                    // Inner AND to allow for all null chart/dept/work area
338                    nullAndWrapper = new Criteria();
339                    nullAndWrapper.addIsNull("workArea");
340                    nullAndWrapper.addIsNull("department");
341                    nullAndWrapper.addIsNull("chart");
342            
343                    nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
344                    nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
345                    nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
346                    orWrapperEd.addOrCriteria(nstWaEd);
347                    orWrapperEd.addOrCriteria(nstDptEd);
348                    orWrapperEd.addOrCriteria(nstChrEd);
349            
350                    // Inner AND to allow for all null chart/dept/work area
351                    orWrapperEd.addOrCriteria(nullAndWrapper);
352            
353                    // Add the inner OR criteria to effective date
354                    timestamp.addAndCriteria(orWrapperEd);
355            
356                    timestampSubQuery = QueryFactory.newReportQuery(TkRole.class, timestamp);
357                    timestampSubQuery.setAttributes(new String[]{"max(timestamp)"});
358            
359                    // Filter by Max(EffDt) / Max(Timestamp)
360                    //root.addEqualTo("effectiveDate", effdtSubQuery);
361                    root.addEqualTo("timestamp", timestampSubQuery);
362            }
363            
364            
365            if (StringUtils.isNotEmpty(roleName)) {
366                root.addEqualTo("roleName", roleName);
367            }
368            
369            if (workArea != null) {
370                root.addEqualTo("workArea", workArea);
371            }
372            
373            if (StringUtils.isNotEmpty(department)) {
374                root.addEqualTo("department", department);
375            }
376            
377            if (StringUtils.isNotEmpty(chart)) {
378                root.addEqualTo("chart", chart);
379            }
380    
381            root.addEqualTo("active", false);
382    
383            Query query = QueryFactory.newQuery(TkRole.class, root);
384            Collection c = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
385    
386            if (c != null) {
387                roles.addAll(c);
388            }
389    
390            return roles;
391        }
392    
393        @Override
394        public void saveOrUpdateRole(TkRole role) {
395            KRADServiceLocator.getBusinessObjectService().save(role);
396        }
397    
398        @Override
399        public void saveOrUpdateRoles(List<TkRole> roles) {
400            if (roles != null) {
401                for (TkRole role : roles) {
402                    saveOrUpdateRole(role);
403                }
404            }
405        }
406    
407        @Override
408        public TkRole getRole(String tkRoleId) {
409            Criteria currentRecordCriteria = new Criteria();
410            currentRecordCriteria.addEqualTo("hrRolesId", tkRoleId);
411    
412            return (TkRole) this.getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(TkRole.class, currentRecordCriteria));
413        }
414    
415        @Override
416        public TkRole getRolesByPosition(String positionNumber) {
417            Criteria currentRecordCriteria = new Criteria();
418            Criteria effdt = new Criteria();
419            currentRecordCriteria.addEqualTo("positionNumber", positionNumber);
420    
421            effdt.addEqualToField("positionNumber", Criteria.PARENT_QUERY_PREFIX + "positionNumber");
422            effdt.addLessOrEqualThan("effectiveDate", TKUtils.getCurrentDate());
423            ReportQueryByCriteria effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
424            effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
425            currentRecordCriteria.addEqualTo("effectiveDate", effdtSubQuery);
426    
427            // Filter for ACTIVE = 'Y'
428            Criteria activeFilter = new Criteria();
429            activeFilter.addEqualTo("active", true);
430            currentRecordCriteria.addAndCriteria(activeFilter);
431    
432    
433            TkRole tkRole = (TkRole) this.getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(TkRole.class, currentRecordCriteria));
434            return tkRole;
435        }
436    
437        @Override
438        public TkRole getInactiveRolesByPosition(String positionNumber) {
439            Criteria currentRecordCriteria = new Criteria();
440            Criteria effdt = new Criteria();
441            currentRecordCriteria.addEqualTo("positionNumber", positionNumber);
442    
443            effdt.addEqualToField("positionNumber", Criteria.PARENT_QUERY_PREFIX + "positionNumber");
444            effdt.addLessOrEqualThan("effectiveDate", TKUtils.getCurrentDate());
445            ReportQueryByCriteria effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
446            effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
447            currentRecordCriteria.addEqualTo("effectiveDate", effdtSubQuery);
448    
449            // Filter for ACTIVE = 'N'
450            Criteria activeFilter = new Criteria();
451            activeFilter.addEqualTo("active", false);
452            currentRecordCriteria.addAndCriteria(activeFilter);
453    
454    
455            TkRole tkRole = (TkRole) this.getPersistenceBrokerTemplate().getObjectByQuery(QueryFactory.newQuery(TkRole.class, currentRecordCriteria));
456            return tkRole;
457        }
458    
459    
460        @Override
461        public List<TkRole> getPositionRolesForWorkArea(Long workArea, Date asOfDate) {
462            List<TkRole> roles = new ArrayList<TkRole>();
463    
464            Criteria root = new Criteria();
465            Criteria effdt = new Criteria();
466            Criteria timestamp = new Criteria();
467            ReportQueryByCriteria effdtSubQuery;
468            ReportQueryByCriteria timestampSubQuery;
469    
470            effdt.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
471            effdt.addEqualToField("positionNumber", Criteria.PARENT_QUERY_PREFIX + "positionNumber");
472            effdt.addLessOrEqualThan("effectiveDate", asOfDate);
473    
474            // EFFECTIVE DATE --
475    
476            // Adding criteria to nest an AND that has multiple ORs to select
477            // the correct ID / date combination.
478            Criteria orWrapperEd = new Criteria();
479            Criteria nstWaEd = new Criteria();
480            Criteria nstDptEd = new Criteria();
481            Criteria nstChrEd = new Criteria();
482    
483            // Inner AND to allow for all null chart/dept/work area
484            Criteria nullAndWrapper = new Criteria();
485            nullAndWrapper.addIsNull("department");
486            nullAndWrapper.addIsNull("chart");
487    
488            nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
489            nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
490            nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
491            orWrapperEd.addOrCriteria(nstWaEd);
492            orWrapperEd.addOrCriteria(nstDptEd);
493            orWrapperEd.addOrCriteria(nstChrEd);
494    
495            // Inner AND to allow for all null chart/dept/work area
496            orWrapperEd.addOrCriteria(nullAndWrapper);
497    
498            // Add the inner OR criteria to effective date
499            effdt.addAndCriteria(orWrapperEd);
500    
501            effdtSubQuery = QueryFactory.newReportQuery(TkRole.class, effdt);
502            effdtSubQuery.setAttributes(new String[]{"max(effectiveDate)"});
503    
504    
505            // TIMESTAMP --
506    
507            //Configure the actual "criteria" in the where clause
508            timestamp.addEqualToField("roleName", Criteria.PARENT_QUERY_PREFIX + "roleName");
509            //timestamp.addEqualToField("principalId", Criteria.PARENT_QUERY_PREFIX + "principalId");
510            timestamp.addEqualToField("effectiveDate", Criteria.PARENT_QUERY_PREFIX + "effectiveDate");
511    
512            // Adding criteria to nest an AND that has multiple ORs to select
513            // the correct ID / date combination.
514            orWrapperEd = new Criteria();
515            nstWaEd = new Criteria();
516            nstDptEd = new Criteria();
517            nstChrEd = new Criteria();
518    
519            // Inner AND to allow for all null chart/dept/work area
520            nullAndWrapper = new Criteria();
521            nullAndWrapper.addIsNull("department");
522            nullAndWrapper.addIsNull("chart");
523    
524            nstWaEd.addEqualToField("workArea", Criteria.PARENT_QUERY_PREFIX + "workArea"); // OR
525            nstDptEd.addEqualToField("department", Criteria.PARENT_QUERY_PREFIX + "department"); // OR
526            nstChrEd.addEqualToField("chart", Criteria.PARENT_QUERY_PREFIX + "chart"); // OR
527            orWrapperEd.addOrCriteria(nstWaEd);
528            orWrapperEd.addOrCriteria(nstDptEd);
529            orWrapperEd.addOrCriteria(nstChrEd);
530    
531            // Inner AND to allow for all null chart/dept/work area
532            orWrapperEd.addOrCriteria(nullAndWrapper);
533    
534            // Add the inner OR criteria to effective date
535            timestamp.addAndCriteria(orWrapperEd);
536    
537            timestampSubQuery = QueryFactory.newReportQuery(TkRole.class, timestamp);
538            timestampSubQuery.setAttributes(new String[]{"max(timestamp)"});
539    
540    
541            // Filter by Max(EffDt) / Max(Timestamp)
542            root.addEqualTo("effectiveDate", effdtSubQuery);
543            root.addEqualTo("timestamp", timestampSubQuery);
544    
545            // Optional ROOT criteria added :
546            if (workArea != null)
547                root.addEqualTo("workArea", workArea);
548            root.addEqualTo("roleName", TkConstants.ROLE_TK_APPROVER);
549    
550            // Filter for ACTIVE = 'Y'
551            Criteria activeFilter = new Criteria();
552            activeFilter.addEqualTo("active", true);
553            root.addAndCriteria(activeFilter);
554    
555            Query query = QueryFactory.newQuery(TkRole.class, root);
556            Collection c = this.getPersistenceBrokerTemplate().getCollectionByQuery(query);
557    
558            if (c != null) {
559                roles.addAll(c);
560            }
561    
562            return roles;
563        }
564    }