Coverage Report - org.kuali.rice.core.api.criteria.QueryByCriteria
 
Classes in this File Line Coverage Branch Coverage Complexity
QueryByCriteria
0%
0/26
0%
0/12
1.85
QueryByCriteria$1
N/A
N/A
1.85
QueryByCriteria$Builder
0%
0/26
0%
0/14
1.85
QueryByCriteria$Constants
0%
0/2
N/A
1.85
QueryByCriteria$Elements
0%
0/1
N/A
1.85
 
 1  
 /*
 2  
  * Copyright 2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.api.criteria;
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.util.Arrays;
 20  
 import java.util.Collection;
 21  
 
 22  
 import javax.xml.bind.annotation.XmlAccessType;
 23  
 import javax.xml.bind.annotation.XmlAccessorType;
 24  
 import javax.xml.bind.annotation.XmlAnyElement;
 25  
 import javax.xml.bind.annotation.XmlElement;
 26  
 import javax.xml.bind.annotation.XmlElements;
 27  
 import javax.xml.bind.annotation.XmlRootElement;
 28  
 import javax.xml.bind.annotation.XmlType;
 29  
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 30  
 
 31  
 import org.apache.commons.lang.builder.EqualsBuilder;
 32  
 import org.apache.commons.lang.builder.HashCodeBuilder;
 33  
 import org.apache.commons.lang.builder.ToStringBuilder;
 34  
 import org.kuali.rice.core.api.CoreConstants;
 35  
 import org.kuali.rice.core.api.mo.ModelBuilder;
 36  
 import org.kuali.rice.core.api.mo.ModelObjectComplete;
 37  
 import org.w3c.dom.Element;
 38  
 
 39  
 /**
 40  
  * Defines a criteria-based query.  Consists of a {@link Predicate} definition
 41  
  * as well as a set of additional properties which control paging and other
 42  
  * aspects of the results which should be returned from the query.
 43  
  * 
 44  
  * <p>In order to construct a new {@link QueryByCriteria}, the {@link Builder}
 45  
  * should be used.  Use the {@link PredicateFactory} to construct
 46  
  * the predicate for use by the query.
 47  
  * 
 48  
  * <p>This class specifies nothing regarding how the query will be executed.
 49  
  * It is expected that an instance will be constructed and then passed to code
 50  
  * which understands how to execute the desired query.
 51  
  * 
 52  
  * <p>This class is mapped for use by JAXB and can therefore be used by clients
 53  
  * as part of remotable service definitions.
 54  
  * 
 55  
  * @see Predicate
 56  
  * @see PredicateFactory
 57  
  * 
 58  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 59  
  * 
 60  
  */
 61  
 @XmlRootElement(name = QueryByCriteria.Constants.ROOT_ELEMENT_NAME)
 62  
 @XmlAccessorType(XmlAccessType.NONE)
 63  
 @XmlType(name = QueryByCriteria.Constants.TYPE_NAME, propOrder = {
 64  
                 QueryByCriteria.Elements.PREDICATE,
 65  
                 QueryByCriteria.Elements.START_AT_INDEX,
 66  
                 QueryByCriteria.Elements.MAX_RESULTS,
 67  
                 QueryByCriteria.Elements.COUNT_FLAG,
 68  
                 CoreConstants.CommonElements.FUTURE_ELEMENTS })
 69  0
 public final class QueryByCriteria implements ModelObjectComplete {
 70  
 
 71  
         private static final long serialVersionUID = 2210627777648920180L;
 72  
 
 73  
     @XmlElements(value = {
 74  
         @XmlElement(name = AndPredicate.Constants.ROOT_ELEMENT_NAME, type = AndPredicate.class, required = false),
 75  
         @XmlElement(name = EqualPredicate.Constants.ROOT_ELEMENT_NAME, type = EqualPredicate.class, required = false),
 76  
         @XmlElement(name = GreaterThanPredicate.Constants.ROOT_ELEMENT_NAME, type = GreaterThanPredicate.class, required = false),
 77  
         @XmlElement(name = GreaterThanOrEqualPredicate.Constants.ROOT_ELEMENT_NAME, type = GreaterThanOrEqualPredicate.class, required = false),
 78  
         @XmlElement(name = InPredicate.Constants.ROOT_ELEMENT_NAME, type = InPredicate.class, required = false),
 79  
         @XmlElement(name = LessThanPredicate.Constants.ROOT_ELEMENT_NAME, type = LessThanPredicate.class, required = false),
 80  
         @XmlElement(name = LessThanOrEqualPredicate.Constants.ROOT_ELEMENT_NAME, type = LessThanOrEqualPredicate.class, required = false),
 81  
         @XmlElement(name = LikePredicate.Constants.ROOT_ELEMENT_NAME, type = LikePredicate.class, required = false),
 82  
         @XmlElement(name = NotEqualPredicate.Constants.ROOT_ELEMENT_NAME, type = NotEqualPredicate.class, required = false),
 83  
         @XmlElement(name = NotInPredicate.Constants.ROOT_ELEMENT_NAME, type = NotInPredicate.class, required = false),
 84  
         @XmlElement(name = NotLikePredicate.Constants.ROOT_ELEMENT_NAME, type = NotLikePredicate.class, required = false),
 85  
         @XmlElement(name = NotNullPredicate.Constants.ROOT_ELEMENT_NAME, type = NotNullPredicate.class, required = false),
 86  
         @XmlElement(name = NullPredicate.Constants.ROOT_ELEMENT_NAME, type = NullPredicate.class, required = false),
 87  
         @XmlElement(name = OrPredicate.Constants.ROOT_ELEMENT_NAME, type = OrPredicate.class, required = false)
 88  
     })
 89  
         private final Predicate predicate;
 90  
         
 91  
         @XmlElement(name = Elements.START_AT_INDEX, required = false)
 92  
         private final Integer startAtIndex;
 93  
                 
 94  
         @XmlElement(name = Elements.MAX_RESULTS, required = false)
 95  
         private final Integer maxResults;
 96  
         
 97  
         @XmlJavaTypeAdapter(CountFlag.Adapter.class)
 98  
         @XmlElement(name = Elements.COUNT_FLAG, required = true)
 99  
         private final String countFlag;
 100  
 
 101  0
         @SuppressWarnings("unused")
 102  
         @XmlAnyElement
 103  
         private final Collection<Element> _futureElements = null;
 104  
 
 105  0
         private QueryByCriteria() {
 106  0
                 this.predicate = null;
 107  0
                 this.startAtIndex = null;
 108  0
                 this.maxResults = null;
 109  0
                 this.countFlag = null;
 110  0
         }
 111  
 
 112  0
         private QueryByCriteria(Builder builder) {
 113  0
                 final Predicate[] preds = builder.predicates;
 114  0
         if (preds != null && preds.length > 1) {
 115  
             //implicit "and"
 116  0
             this.predicate = PredicateFactory.and(builder.predicates);
 117  0
         } else if (preds != null && preds.length == 1) {
 118  0
             this.predicate = builder.predicates[0];
 119  
         } else {
 120  0
             this.predicate = null;
 121  
         }
 122  
 
 123  0
                 this.startAtIndex = builder.getStartAtIndex();
 124  0
                 this.maxResults = builder.getMaxResults();
 125  0
                 this.countFlag = builder.getCountFlag() == null ? null : builder.getCountFlag().getFlag();
 126  0
         }
 127  
 
 128  
         /**
 129  
          * Returns the {@link Predicate} which will be used to execute the query.
 130  
          * 
 131  
          * @return can be null if no predicate was specified
 132  
          */
 133  
         public Predicate getPredicate() {
 134  0
                 return this.predicate;
 135  
         }
 136  
 
 137  
         /**
 138  
          * Returns the optional zero-based "start" index for rows returned.  When
 139  
          * this query is executed, this property should be read to determine the
 140  
          * first row which should be returned.  If the given index is beyond the
 141  
          * end of the result set, then the resulting query should effectively
 142  
          * return no rows (as opposed to producing an index-based out of bounds
 143  
          * error).  If the value is null, then the results should start with the
 144  
          * first row returned from the query.
 145  
          *
 146  
      * <p>
 147  
      * Will never be less than 0
 148  
      *
 149  
          * @return the starting row index requested by this query, or null if
 150  
          * the results should start at the beginning of the result set
 151  
          */
 152  
         public Integer getStartAtIndex() {
 153  0
                 return this.startAtIndex;
 154  
         }
 155  
 
 156  
         /**
 157  
          * Returns the maximum number of results that this query is requesting
 158  
          * to receive.  If null, then the query should return all rows, or as
 159  
          * many as it can.  If the number request is larger than the number of
 160  
      * results then all results are returned.
 161  
          *
 162  
      * <p>
 163  
      * Will never be less than 0
 164  
      *
 165  
          * @return the maximum number of results to return from the query
 166  
          */
 167  
         public Integer getMaxResults() {
 168  0
                 return this.maxResults;
 169  
         }
 170  
 
 171  
         /**
 172  
          * Indicates whether or not a total row count should be returned with the
 173  
          * query.  See {@link CountFlag} for more information on what each of these
 174  
          * flags means.  This will never return null and defaults to
 175  
          * {@link CountFlag#NONE}.
 176  
          * 
 177  
          * @return the flag specifying whether or not a total row count should be
 178  
          * produced by the query
 179  
          */
 180  
         public CountFlag getCountFlag() {
 181  0
                 return this.countFlag == null ? null : CountFlag.valueOf(this.countFlag);
 182  
         }
 183  
 
 184  
         @Override
 185  
         public int hashCode() {
 186  0
                 return HashCodeBuilder.reflectionHashCode(this,
 187  
                                 Constants.HASH_CODE_EQUALS_EXCLUDE);
 188  
         }
 189  
 
 190  
         @Override
 191  
         public boolean equals(Object obj) {
 192  0
                 return EqualsBuilder.reflectionEquals(obj, this,
 193  
                                 Constants.HASH_CODE_EQUALS_EXCLUDE);
 194  
         }
 195  
 
 196  
         @Override
 197  
         public String toString() {
 198  0
                 return ToStringBuilder.reflectionToString(this);
 199  
         }
 200  
 
 201  0
         public static final class Builder implements ModelBuilder, Serializable {
 202  
 
 203  
                 private Predicate[] predicates;
 204  
                 private Integer startAtIndex;
 205  
                 private Integer maxResults;
 206  
                 private CountFlag countFlag;
 207  
 
 208  0
                 private Builder() {
 209  0
                         this.countFlag = CountFlag.NONE;
 210  0
                 }
 211  
 
 212  
                 public static Builder create() {
 213  0
             return new Builder();
 214  
                 }
 215  
 
 216  
                 public Integer getStartAtIndex() {
 217  0
             return this.startAtIndex;
 218  
                 }
 219  
 
 220  
                 public void setStartAtIndex(Integer startAtIndex) {
 221  0
             if (startAtIndex != null && startAtIndex < 0) {
 222  0
                 throw new IllegalArgumentException("startAtIndex < 0");
 223  
             }
 224  
 
 225  0
             this.startAtIndex = startAtIndex;
 226  0
                 }
 227  
 
 228  
                 public Integer getMaxResults() {
 229  0
                         return this.maxResults;
 230  
                 }
 231  
 
 232  
                 public void setMaxResults(Integer maxResults) {
 233  0
                         if (maxResults != null && maxResults < 0) {
 234  0
                 throw new IllegalArgumentException("maxResults < 0");
 235  
             }
 236  
 
 237  0
             this.maxResults = maxResults;
 238  0
                 }
 239  
 
 240  
                 public CountFlag getCountFlag() {
 241  0
                         return this.countFlag;
 242  
                 }
 243  
 
 244  
                 public void setCountFlag(CountFlag countFlag) {
 245  0
                         if (countFlag == null) {
 246  0
                 throw new IllegalArgumentException("countFlag was null");
 247  
             }
 248  
 
 249  0
             this.countFlag = countFlag;
 250  0
                 }
 251  
 
 252  
         /**
 253  
          * will return an array of the predicates.  may return null if no predicates were set.
 254  
          * @return the predicates
 255  
          */
 256  
                 public Predicate[] getPredicates() {
 257  0
                         if (this.predicates == null) {
 258  0
                 return null;
 259  
             }
 260  
 
 261  
                         //defensive copies on array
 262  0
             return Arrays.copyOf(predicates, predicates.length);
 263  
                 }
 264  
 
 265  
         /**
 266  
          * Sets the predicates. If multiple predicates are specified then they are wrapped
 267  
          * in an "and" predicate. If a null predicate is specified then there will be no
 268  
          * constraints on the query.
 269  
          * @param predicates the predicates to set.
 270  
          */
 271  
         public void setPredicates(Predicate... predicates) {
 272  
             //defensive copies on array
 273  0
             this.predicates = predicates != null ? Arrays.copyOf(predicates, predicates.length) : null;
 274  0
                 }
 275  
 
 276  
         @Override
 277  
         public QueryByCriteria build() {
 278  0
             return new QueryByCriteria(this);
 279  
         }
 280  
     }
 281  
 
 282  
         /**
 283  
          * Defines some internal constants used on this class.
 284  
          */
 285  0
         static class Constants {
 286  
                 final static String ROOT_ELEMENT_NAME = "queryByCriteria";
 287  
                 final static String TYPE_NAME = "QueryByCriteriaType";
 288  0
                 final static String[] HASH_CODE_EQUALS_EXCLUDE = { CoreConstants.CommonElements.FUTURE_ELEMENTS };
 289  
         }
 290  
 
 291  
         /**
 292  
          * A private class which exposes constants which define the XML element
 293  
          * names to use when this object is marshaled to XML.
 294  
          */
 295  0
         static class Elements {
 296  
                 final static String PREDICATE = "predicate";
 297  
                 final static String START_AT_INDEX = "startAtIndex";
 298  
                 final static String MAX_RESULTS = "maxResults";
 299  
                 final static String COUNT_FLAG = "countFlag";
 300  
         }
 301  
 
 302  
 }