View Javadoc
1   /**
2    * Copyright 2005-2016 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.kim.api.common.history;
17  
18  import org.joda.time.DateTime;
19  import org.kuali.rice.core.api.criteria.OrderByField;
20  import org.kuali.rice.core.api.criteria.OrderDirection;
21  import org.kuali.rice.core.api.criteria.Predicate;
22  import org.kuali.rice.core.api.criteria.QueryByCriteria;
23  
24  import java.sql.Timestamp;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
29  
30  public final class HistoryQueryUtils {
31  
32      private HistoryQueryUtils() {
33          throw new UnsupportedOperationException();
34      }
35  
36      public static QueryByCriteria historyQuery(String id, DateTime asOfDate) {
37          Timestamp asOfTimestamp = new Timestamp(asOfDate.getMillis());
38          Predicate predicate =
39              and(
40                  equal("id", id),
41                  and(
42                      or(isNull("activeFromDateValue"), lessThanOrEqual("activeFromDateValue", asOfTimestamp)),
43                      or(isNull("activeToDateValue"), greaterThan("activeToDateValue", asOfTimestamp))
44                  )
45              );
46  
47          QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create();
48          criteria.setMaxResults(Integer.valueOf(1));
49          criteria.setPredicates(predicate);
50          List<OrderByField> orderByFields = new ArrayList<OrderByField>();
51          orderByFields.add(OrderByField.Builder.create("activeFromDateValue", OrderDirection.DESCENDING).build());
52          orderByFields.add(OrderByField.Builder.create("historyId", OrderDirection.DESCENDING).build());
53          criteria.setOrderByFields(orderByFields);
54  
55          return criteria.build();
56      }
57  
58      public static QueryByCriteria futureRecordQuery(String id, DateTime asOfDate) {
59          Timestamp asOfTimestamp = new Timestamp(asOfDate.getMillis());
60          Predicate predicate =
61                  and(
62                      equal("id", id),
63                      or(isNull("activeFromDateValue"), greaterThan("activeFromDateValue", asOfTimestamp))
64                  );
65  
66          QueryByCriteria.Builder criteria = QueryByCriteria.Builder.create();
67          criteria.setMaxResults(Integer.valueOf(1));
68          criteria.setPredicates(predicate);
69          List<OrderByField> orderByFields = new ArrayList<OrderByField>();
70          orderByFields.add(OrderByField.Builder.create("activeFromDateValue", OrderDirection.DESCENDING).build());
71          orderByFields.add(OrderByField.Builder.create("historyId", OrderDirection.DESCENDING).build());
72          criteria.setOrderByFields(orderByFields);
73  
74          return criteria.build();
75      }
76  
77      public static Predicate between(String startField,String endField, DateTime asOfDate) {
78          // the precision of this check should be to the second, not milliseconds, so we want to chop off any
79          // milliseconds and do a ceiling of our seconds. Sometimes changes are made in near real time after a record
80          // becomes activated or inactivated so we want to have the best result possible if they are still within the
81          // same second, so we essentially always round up to ensure that this check will never fail in high throughput
82          // environments
83          asOfDate = asOfDate.secondOfDay().roundCeilingCopy();
84          return
85                  and(
86                      or(isNull(startField), lessThanOrEqual(startField, asOfDate.toDate())),
87                      or(isNull(endField), greaterThan(endField, asOfDate.toDate()))
88                  );
89      }
90  }