Coverage Report - org.kuali.rice.core.framework.persistence.jdbc.sql.Criteria
 
Classes in this File Line Coverage Branch Coverage Complexity
Criteria
0%
0/233
0%
0/128
2.674
Criteria$AndCriteria
0%
0/5
N/A
2.674
Criteria$ExistsCriteria
0%
0/5
N/A
2.674
Criteria$OrCriteria
0%
0/5
N/A
2.674
 
 1  
 /*
 2  
  * Copyright 2007-2008 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.core.framework.persistence.jdbc.sql;
 17  
 
 18  
 import java.math.BigDecimal;
 19  
 import java.sql.Timestamp;
 20  
 import java.text.ParseException;
 21  
 import java.text.SimpleDateFormat;
 22  
 import java.util.ArrayList;
 23  
 import java.util.HashMap;
 24  
 import java.util.Iterator;
 25  
 import java.util.LinkedHashMap;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 
 29  
 import javax.persistence.Query;
 30  
 
 31  
 import org.kuali.rice.core.api.datetime.DateTimeService;
 32  
 import org.kuali.rice.core.api.CoreConstants;
 33  
 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
 34  
 import org.kuali.rice.core.framework.persistence.platform.DatabasePlatform;
 35  
 import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria.QueryByCriteriaType;
 36  
 import org.kuali.rice.core.util.RiceConstants;
 37  
 import org.kuali.rice.core.util.type.TypeUtils;
 38  
 import org.kuali.rice.core.web.format.BooleanFormatter;
 39  
 
 40  
 
 41  
 
 42  
 /**
 43  
  * A criteria builder for JDBC Query strings.
 44  
  *
 45  
  * TODO: Rewrite this class with a better criteria building algorithm.
 46  
  *
 47  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 48  
  */
 49  
 @SuppressWarnings("unchecked")
 50  0
 public class Criteria {
 51  0
         private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(Criteria.class);
 52  
 
 53  
         private Integer searchLimit;
 54  
 
 55  
         private String entityName;
 56  
 
 57  
         private String alias;
 58  
 
 59  0
         private boolean distinct = false;
 60  
         
 61  
         private transient DateTimeService dateTimeService;
 62  
 
 63  0
         protected List tokens = new ArrayList();
 64  
 
 65  0
         private List orderByTokens = new ArrayList();
 66  
 
 67  0
         protected Map<String, Object> params = new LinkedHashMap<String, Object>();
 68  
 
 69  0
         DatabasePlatform dbPlatform = null;
 70  
 
 71  
         public Criteria(String entityName) {
 72  0
                 this(entityName, "a");
 73  0
         }
 74  
 
 75  
         public DatabasePlatform getDbPlatform() {
 76  0
             if (dbPlatform == null) {
 77  0
                     dbPlatform = (DatabasePlatform) GlobalResourceLoader.getService(RiceConstants.DB_PLATFORM);
 78  
             }
 79  0
             return dbPlatform;
 80  
     }
 81  
 
 82  
         public void setDbPlatform(DatabasePlatform dbPlatform){
 83  0
                 this.dbPlatform = dbPlatform;
 84  0
         }
 85  
 
 86  0
         public Criteria(String entityName, String alias) {
 87  0
                 this.entityName = entityName;
 88  0
                 this.alias = alias;
 89  0
         }
 90  
 
 91  
         public void between(String attribute, Object value1, Object value2, Class propertyType) {
 92  
 
 93  0
                 String fixedValue1 = this.fixValue(value1, propertyType);
 94  0
                 String fixedValue2= this.fixValue(value2, propertyType);
 95  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 96  0
                         tokens.add(" (" + fix(attribute) + " BETWEEN " + fixedValue1 + " AND " + fixedValue2 + ") ");
 97  
                 } else {
 98  0
                         tokens.add(" (" + alias + "." + attribute + " BETWEEN " + fixedValue1 + " AND " + fixedValue2 + ") ");
 99  
                 }
 100  
 
 101  0
         }
 102  
 
 103  
         private String fixValue(Object value, Class propertyType){
 104  
                 
 105  0
                 if (value == null) {
 106  0
                         return "";
 107  
                 }
 108  
 
 109  0
                 if(TypeUtils.isJoinClass(propertyType)){
 110  0
                         return value.toString();
 111  
                 }
 112  
 
 113  0
                 if(TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType)){
 114  0
                         new BigDecimal(value.toString()); // This should throw an exception if the number is invalid.
 115  0
                         return value.toString();
 116  
                 }
 117  0
                 if(TypeUtils.isTemporalClass(propertyType)){
 118  
                         try {
 119  0
                                 if (value instanceof String) {
 120  0
                                         value = getDateTimeService().convertToSqlTimestamp(value.toString());
 121  
                                 }
 122  0
                                 return getFixedTemporalValue(value);
 123  0
                         } catch (ParseException pe) {
 124  0
                                 LOG.warn("Could not parse "+value.toString()+" as date");
 125  0
                                 throw new RuntimeException("Could not parse "+value.toString()+" as date", pe);
 126  
                         }
 127  
                 }
 128  0
                 if (TypeUtils.isStringClass(propertyType)) {
 129  0
                         return " '" + getDbPlatform().escapeString(value.toString().trim()) + "' ";
 130  
                 }
 131  0
                 if (TypeUtils.isBooleanClass(propertyType)) {
 132  0
                         if (value instanceof String) {
 133  0
                                 value = new BooleanFormatter().convertFromPresentationFormat(value.toString());
 134  
                         }
 135  0
                         boolean bVal = ((Boolean)value).booleanValue();
 136  0
                         if(bVal){return "1";}
 137  0
                         else { return "0";}
 138  
                 }
 139  
 
 140  0
                 return value.toString();
 141  
         }
 142  
         
 143  
         /**
 144  
          * Prepares a temporally classed value for inclusion in criteria
 145  
          * @param value the Timestamp value to convert
 146  
          * @return the fixed SQL version of that value
 147  
          */
 148  
         private String getFixedTemporalValue(Object value) {
 149  0
                 Timestamp ts = (Timestamp)value;
 150  0
                 java.sql.Date dt = new java.sql.Date(ts.getTime());
 151  0
                 SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
 152  0
                 SimpleDateFormat sdfTime = new SimpleDateFormat("HH:mm:ss");
 153  
 
 154  0
                 String sql = getDbPlatform().getDateSQL(sdfDate.format(dt),sdfTime.format(dt)) ;
 155  0
                 return sql;
 156  
         }
 157  
 
 158  
 
 159  
         /**
 160  
          * This method ...
 161  
          *
 162  
          * @param string
 163  
          * @return
 164  
          */
 165  
 /*
 166  
         private String fixAttr(String attr) {
 167  
                 return "?";
 168  
                 //return fixAttr(attr,0);
 169  
         }
 170  
         private String fixAttr(String attr, int cnt) {
 171  
                 String sRet = attr.replace(".", "_");
 172  
 
 173  
                 if(params.containsKey(sRet)){
 174  
                         sRet = fixAttr(attr, ++cnt);
 175  
                 }
 176  
                 return sRet;
 177  
         }
 178  
 */
 179  
         public void eq(String attribute, Object value, Class propertyType) {
 180  
 
 181  0
                 tokens.add(alias + "." + attribute + " = " + fixValue(value, propertyType) + " ");
 182  
 
 183  0
         }
 184  
 
 185  
         public void gt(String attribute, Object value, Class propertyType) {
 186  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 187  0
                         tokens.add(fix(attribute) + " > " + fixValue(value, propertyType) + " ");
 188  
                 } else {
 189  0
                         tokens.add(alias + "." + attribute + " > " + fixValue(value, propertyType) + " ");
 190  
                 }
 191  
 
 192  0
         }
 193  
 
 194  
         public void gte(String attribute, Object value, Class propertyType) {
 195  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 196  0
                         tokens.add(fix(attribute) + " >= " + fixValue(value, propertyType) + " ");
 197  
                 } else {
 198  0
                         tokens.add(alias + "." + attribute + " >= " + fixValue(value, propertyType) + " ");
 199  
                 }
 200  0
         }
 201  
 
 202  
         public void like(String attribute, Object value, Class propertyType, boolean allowWildcards) {
 203  0
                 String fixedValue = fixValue(value, propertyType);
 204  
 
 205  0
                 if(allowWildcards){
 206  0
                         fixedValue = fixWildcards(stripFunctions(fixedValue));
 207  
                 }
 208  
 
 209  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 210  0
                         tokens.add(fix(attribute) + " LIKE " +  fixedValue + " ");
 211  
                 } else {
 212  0
                         tokens.add(alias + "." + attribute + " LIKE " + fixedValue + " ");
 213  
                 }
 214  0
         }
 215  
 
 216  
         public void notLike(String attribute, Object value, Class propertyType, boolean allowWildcards) {
 217  0
                 String fixedValue = fixValue(value, propertyType);
 218  
 
 219  0
                 if(allowWildcards){
 220  0
                         fixedValue = fixWildcards(stripFunctions(fixedValue));
 221  
                 }
 222  
 
 223  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 224  0
                         tokens.add(fix(attribute) + " NOT LIKE " + fixedValue + " ");
 225  
                 } else {
 226  0
                         tokens.add(alias + "." + attribute + " NOT LIKE " + fixedValue + " ");
 227  
                 }
 228  
                 //tokens.add(alias + "." + attribute + " NOT LIKE " + stripFunctions(fixedValue).replaceAll("\\*", "%") + " ");
 229  0
         }
 230  
 
 231  
         private static String fixWildcards(String sIn){
 232  0
                 String sRet = sIn.replaceAll("\\*", "%");
 233  0
                 return sRet.replaceAll("\\?", "_");
 234  
         }
 235  
 
 236  
         public void lt(String attribute, Object value, Class propertyType) {
 237  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 238  0
                         tokens.add(fix(attribute) + " < " + fixValue(value, propertyType) + " ");
 239  
                 } else {
 240  0
                         tokens.add(alias + "." + attribute + " < " + fixValue(value, propertyType) + " ");
 241  
                 }
 242  0
         }
 243  
 
 244  
         public void lte(String attribute, Object value, Class propertyType) {
 245  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 246  0
                         tokens.add(fix(attribute) + " <= " + fixValue(value, propertyType) + " ");
 247  
                 } else {
 248  0
                         tokens.add(alias + "." + attribute + " <= " + fixValue(value, propertyType) + " ");
 249  
                 }
 250  0
         }
 251  
 
 252  
         public void ne(String attribute, Object value, Class propertyType) {
 253  0
                 tokens.add(alias + "." + attribute + " != " + fixValue(value, propertyType) + " ");
 254  0
         }
 255  
 
 256  
         public void isNull(String attribute) {
 257  0
                 tokens.add(alias + "." + attribute + " IS NULL ");
 258  0
         }
 259  
 
 260  
         public void rawJpql(String jpql) {
 261  0
                 tokens.add(" " + jpql + " ");
 262  0
         }
 263  
 
 264  
         public void in(String attribute, List values, Class propertyType) {
 265  0
                 String in = "";
 266  0
                 for (Object object : values) {
 267  0
                         in += fixValue(object, propertyType) + ",";
 268  
                 }
 269  0
                 if (!"".equals(in)) {
 270  0
                         in = in.substring(0, in.length()-1);
 271  
                 }
 272  0
                 tokens.add(alias + "." + attribute + " IN (" + in + ") ");
 273  0
         }
 274  
 
 275  
         public void notIn(String attribute, List values, Class propertyType) {
 276  0
                 String in = "";
 277  0
                 for (Object object : values) {
 278  0
                         in += fixValue(object, propertyType) + ",";
 279  
                 }
 280  0
                 if (!"".equals(in)) {
 281  0
                         in = in.substring(in.length()-1);
 282  
                 }
 283  0
                 tokens.add(alias + "." + attribute + " NOT IN (" + in + ") ");
 284  0
         }
 285  
 
 286  
         public void orderBy(String attribute, boolean sortAscending) {
 287  0
                 String sort = (sortAscending ? "ASC" : "DESC");
 288  0
                 orderByTokens.add(alias + "." + attribute + " " + sort + " ");
 289  0
         }
 290  
 
 291  
         public void and(Criteria and) {
 292  0
                 tokens.add(new AndCriteria(and));
 293  0
         }
 294  
 
 295  
         public void or(Criteria or) {
 296  0
                 tokens.add(new OrCriteria(or));
 297  0
         }
 298  
 
 299  
         public void exists(Criteria exists) {
 300  0
         tokens.add(new ExistsCriteria(exists));
 301  0
     }
 302  
         
 303  
         public String toQuery(QueryByCriteriaType type) {
 304  0
                 String queryType = type.toString();
 305  0
                 if (type.equals(QueryByCriteriaType.SELECT)) {
 306  0
                         if(distinct){
 307  0
                                 queryType += " " + "DISTINCT";
 308  
                         }
 309  
 
 310  0
                         queryType += " " + alias;
 311  
                 }
 312  0
                 String queryString = queryType + " FROM " + entityName + " AS " + alias;
 313  0
                 if (!tokens.isEmpty()) {
 314  0
                         queryString += " WHERE " + buildWhere();
 315  
                 }
 316  0
                 if (!orderByTokens.isEmpty()) {
 317  0
                         queryString += " ORDER BY ";
 318  0
                         int count = 0;
 319  0
                         for (Iterator iterator = orderByTokens.iterator(); iterator.hasNext();) {
 320  0
                                 Object token = (Object) iterator.next();
 321  0
                                 if (count == 0) {
 322  0
                                         count++;
 323  
                                 } else {
 324  0
                                         queryString += ", ";
 325  
                                 }
 326  0
                                 queryString += (String) token;
 327  0
                         }
 328  
                 }
 329  0
                 return fix(queryString);
 330  
         }
 331  
 
 332  
         public String toCountQuery() {
 333  0
                 String queryString = "SELECT COUNT(*) FROM " + entityName + " AS " + alias;
 334  0
                 if (!tokens.isEmpty()) {
 335  0
                         queryString += " WHERE " + buildWhere();
 336  
                 }
 337  0
                 return fix(queryString);
 338  
         }
 339  
 
 340  
         private String fix(String queryString) {
 341  0
                 queryString = queryString.replaceAll("__JPA_ALIAS__", alias);
 342  0
                 return queryString;
 343  
         }
 344  
 
 345  
         public String buildWhere() {
 346  0
                 return fix(buildWhere(null));
 347  
         }
 348  
 
 349  
         private String buildWhere(Criteria parentCriteria) {
 350  0
                 String queryString = "";
 351  0
                 int i = 0;
 352  0
                 for (Iterator iterator = tokens.iterator(); iterator.hasNext();) {
 353  0
                         Object token = (Object) iterator.next();
 354  0
                         if (token instanceof Criteria) {
 355  0
                                 String logic = "";
 356  0
                                 if (i>0 && token instanceof AndCriteria) {
 357  0
                                         logic = " AND ";
 358  0
                                 } else if (i>0 && token instanceof OrCriteria) {
 359  0
                                         logic = " OR ";
 360  0
                                 } else if (i>0 && token instanceof ExistsCriteria) {
 361  0
                     logic = " EXISTS ";
 362  
                 }
 363  0
                         queryString += logic + " (" + ((Criteria) token).buildWhere(((Criteria) token)) + ") ";
 364  0
                         } else {
 365  0
                                 if(i>0){
 366  0
                                         queryString += " AND " + (String) token;
 367  
                                 }else{
 368  0
                                         queryString += (String) token;
 369  
                                 }
 370  
                         }
 371  0
                         i++;
 372  0
                 }
 373  0
                 return queryString;
 374  
         }
 375  
 
 376  
         // Keep this package access so the QueryByCriteria can call it from this package.
 377  
         void prepareParameters(Query query) {
 378  0
                 prepareParameters(query, tokens, params);
 379  0
         }
 380  
 
 381  
         public List<Object> getParameteres() {
 382  0
                 return getParameteres(tokens, params);
 383  
         }
 384  
 
 385  
         public List<Object> getParameteres(List tokens, Map<String, Object> params) {
 386  
 
 387  0
                 List<Object> mRet = new ArrayList<Object>();
 388  
 
 389  0
                 for (Map.Entry<String, Object> param : params.entrySet()) {
 390  0
                         Object value = param.getValue();
 391  0
                         if (value instanceof BigDecimal) {
 392  0
                                 value = new Long(((BigDecimal)value).longValue());
 393  
                         }
 394  0
                         if (value instanceof String) {
 395  0
                                 value = ((String)value).replaceAll("\\*", "%");
 396  
                         }
 397  0
                         mRet.add(value);
 398  0
                 }
 399  0
                 for (Iterator iterator = tokens.iterator(); iterator.hasNext();) {
 400  0
                         Object token = (Object) iterator.next();
 401  0
                         if (token instanceof Criteria) {
 402  0
                                 mRet.addAll(getParameteres(((Criteria)token).tokens, ((Criteria)token).params));
 403  
                         }
 404  0
                 }
 405  0
                 return mRet;
 406  
         }
 407  
 
 408  
         void prepareParameters(Query query, List tokens, Map<String, Object> params) {
 409  0
                 for (Map.Entry<String, Object> param : params.entrySet()) {
 410  0
                         Object value = param.getValue();
 411  0
                         if (value instanceof BigDecimal) {
 412  0
                                 value = new Long(((BigDecimal)value).longValue());
 413  
                         }
 414  0
                         if (value instanceof String) {
 415  0
                                 value = ((String)value).replaceAll("\\*", "%");
 416  
                         }
 417  0
                         query.setParameter(param.getKey(), value);
 418  0
                 }
 419  0
                 for (Iterator iterator = tokens.iterator(); iterator.hasNext();) {
 420  0
                         Object token = (Object) iterator.next();
 421  0
                         if (token instanceof Criteria) {
 422  0
                                 prepareParameters(query, ((Criteria)token).tokens, ((Criteria)token).params);
 423  
                         }
 424  0
                 }
 425  0
         }
 426  
 
 427  
         private class AndCriteria extends Criteria {
 428  0
                 public AndCriteria(Criteria and) {
 429  0
                         super(and.entityName, and.alias);
 430  0
                         this.tokens = new ArrayList(and.tokens);
 431  0
                         this.params = new HashMap(and.params);
 432  0
                 }
 433  
         }
 434  
 
 435  
         private class OrCriteria extends Criteria {
 436  0
                 public OrCriteria(Criteria or) {
 437  0
                         super(or.entityName, or.alias);
 438  0
                         this.tokens = new ArrayList(or.tokens);
 439  0
                         this.params = new HashMap(or.params);
 440  0
                 }
 441  
         }
 442  
         
 443  
         private class ExistsCriteria extends Criteria {
 444  0
         public ExistsCriteria(Criteria exists) {
 445  0
             super(exists.entityName, exists.alias);
 446  0
             this.tokens = new ArrayList(exists.tokens);
 447  0
             this.params = new HashMap(exists.params);
 448  0
         }       
 449  
     }
 450  
 
 451  
         public Integer getSearchLimit() {
 452  0
                 return this.searchLimit;
 453  
         }
 454  
 
 455  
         public void setSearchLimit(Integer searchLimit) {
 456  0
                 this.searchLimit = searchLimit;
 457  0
         }
 458  
 
 459  
 
 460  
         public void notNull(String attribute) {
 461  0
                 tokens.add(alias + "." + attribute + " IS NOT NULL ");
 462  0
         }
 463  
 
 464  
         public void distinct(boolean distinct){
 465  0
                 this.distinct = distinct;
 466  0
         }
 467  
 
 468  
         /**
 469  
          * This method ...
 470  
          *
 471  
          * @param string
 472  
          * @param timestamp
 473  
          * @param timestamp2
 474  
          */
 475  
         public void notBetween(String attribute, Object value1,
 476  
                         Object value2, Class propertyType) {
 477  0
                 String fixedValue1 = fixValue(value1, propertyType);
 478  0
                 String fixedValue2 = fixValue(value1, propertyType);
 479  0
                 if (attribute.contains("__JPA_ALIAS__")) {
 480  0
                         tokens.add(" (" + fix(attribute) + " NOT BETWEEN " + fixedValue1 + " AND " + fixedValue2 + ") ");
 481  
                 } else {
 482  0
                         tokens.add(" (" + alias + "." + attribute + " NOT BETWEEN " + fixedValue1 + " AND " + fixedValue2 + ") ");
 483  
                 }
 484  
 
 485  0
         }
 486  
 
 487  
         /**
 488  
          * This method ...
 489  
          *
 490  
          * @param string
 491  
          * @param responsibilitySubQuery
 492  
          */
 493  
         public void in(String match, Criteria subQuery, String attribute, Class propertyType) {
 494  0
                 if("a".equals(subQuery.alias)){
 495  0
                         subQuery.alias="b";
 496  
                 }
 497  0
                 String whereClause = "";
 498  0
                 if(subQuery.tokens.isEmpty()){
 499  0
                         whereClause = "WHERE ";
 500  
                 }else{
 501  0
                         whereClause = "AND ";
 502  
                 }
 503  0
                 whereClause += subQuery.alias+"."+attribute + " = " + alias+"."+match;
 504  
 
 505  0
                 tokens.add("EXISTS (" + subQuery.toQuery(QueryByCriteriaType.SELECT) + whereClause + " ) ");
 506  
 
 507  0
         }
 508  
 
 509  
         private String stripFunctions(String attribute) {
 510  0
             int index = attribute.lastIndexOf('(');
 511  0
             if(index != -1) {
 512  0
                 return attribute.substring(index+1, attribute.indexOf(')'));
 513  
             }
 514  
 
 515  0
             return attribute;
 516  
         }
 517  
         public String getAlias(){
 518  0
                 return this.alias;
 519  
         }
 520  
 
 521  
         public String establishDateString(String fromDate, String toDate, String columnDbName, String whereStatementClause) {
 522  0
             DatabasePlatform platform = getDbPlatform();
 523  0
             StringBuffer dateSqlString = new StringBuffer(whereStatementClause).append(" " + platform.escapeString(columnDbName) + " ");
 524  0
         if (fromDate != null && SQLUtils.getSqlFormattedDate(fromDate) != null && toDate != null && SQLUtils.getSqlFormattedDate(toDate) != null) {
 525  0
             return dateSqlString.append(" >= " + platform.getDateSQL(platform.escapeString(SQLUtils.getSqlFormattedDate(fromDate.trim())), null) + " and " + platform.escapeString(columnDbName) + " <= " + platform.getDateSQL(platform.escapeString(SQLUtils.getSqlFormattedDate(toDate.trim())), "23:59:59")).toString();
 526  
         } else {
 527  0
             if (fromDate != null && SQLUtils.getSqlFormattedDate(fromDate) != null) {
 528  0
                 return dateSqlString.append(" >= " + platform.getDateSQL(platform.escapeString(SQLUtils.getSqlFormattedDate(fromDate.trim())), null)).toString();
 529  0
             } else if (toDate != null && SQLUtils.getSqlFormattedDate(toDate) != null) {
 530  0
                 return dateSqlString.append(" <= " + platform.getDateSQL(platform.escapeString(SQLUtils.getSqlFormattedDate(toDate.trim())), "23:59:59")).toString();
 531  
             } else {
 532  0
                 return "";
 533  
             }
 534  
         }
 535  
     }
 536  
         
 537  
         private DateTimeService getDateTimeService() {
 538  0
             if (this.dateTimeService == null) {
 539  0
                     this.dateTimeService = GlobalResourceLoader.getService(CoreConstants.Services.DATETIME_SERVICE);
 540  
             }
 541  0
             return this.dateTimeService;
 542  
     }
 543  
 }