001: /*
002: * Copyright 2004-2007 Gary Bentley
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may
005: * not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015: package org.josql.internal;
016:
017: import java.util.List;
018: import java.util.ArrayList;
019:
020: import org.josql.expressions.ValueExpression;
021:
022: import org.josql.Query;
023: import org.josql.QueryParseException;
024: import org.josql.QueryExecutionException;
025:
026: public class Limit {
027:
028: private ValueExpression start = null;
029: private ValueExpression rowsCount = null;
030:
031: public Limit() {
032:
033: }
034:
035: public void init(Query q) throws QueryParseException {
036:
037: // Init the value expressions...
038: if (this .start != null) {
039:
040: this .start.init(q);
041:
042: // Should probably check to ensure that accessors aren't used... since
043: // we don't have a "current object" to work on!.
044: Class c = this .start.getExpectedReturnType(q);
045:
046: if (!Utilities.isNumber(c)) {
047:
048: throw new QueryParseException(
049: "The expected return type of the start expression: \""
050: + this .start
051: + "\" of the LIMIT clause is: "
052: + c.getName()
053: + " however the expression when evaluated must return a numeric result.");
054:
055: }
056:
057: }
058:
059: this .rowsCount.init(q);
060:
061: // Should probably check to ensure that accessors aren't used... since
062: // we don't have a "current object" to work on!.
063:
064: // Try and determine what the expected type is that we will return.
065: Class c = this .rowsCount.getExpectedReturnType(q);
066:
067: if (!Utilities.isNumber(c)) {
068:
069: throw new QueryParseException(
070: "The expected return type of the rows count expression: \""
071: + this .rowsCount
072: + "\" of the LIMIT clause is: "
073: + c.getName()
074: + " however the expression when evaluated must return a numeric result.");
075:
076: }
077:
078: }
079:
080: public List getSubList(List objs, Query q)
081: throws QueryExecutionException {
082:
083: // Get the row count.
084: Object o = this .rowsCount.evaluate(null, q);
085:
086: int rows = -1;
087:
088: // Ensure that it is a number.
089: if ((o != null) && (!(o instanceof Number))) {
090:
091: throw new QueryExecutionException(
092: "Return value of rows count expression: \""
093: + this .rowsCount
094: + "\" for the LIMIT clause is of type: "
095: + o.getClass().getName()
096: + " expected it to return a numeric value.");
097:
098: }
099:
100: if (o != null) {
101:
102: // There are rounding issues here, but if the user provides a float/double value...
103: rows = ((Number) o).intValue();
104:
105: }
106:
107: int start = 0;
108:
109: // Now get the start value...
110: if (this .start != null) {
111:
112: Object s = this .start.evaluate(null, q);
113:
114: // Ensure that it is a number.
115: if ((s != null) && (!(s instanceof Number))) {
116:
117: throw new QueryExecutionException(
118: "Return value of the start expression: \""
119: + this .start
120: + "\" for the LIMIT clause is of type: "
121: + s.getClass().getName()
122: + " expected it to return a numeric value.");
123:
124: }
125:
126: if (s != null) {
127:
128: // There are rounding issues here, but if the user provides a float/double value...
129: start = ((Number) s).intValue();
130:
131: // Whilst for the user rows start at 1, for us they start at 0...
132: start--;
133:
134: }
135:
136: }
137:
138: int ls = objs.size();
139:
140: // Now get our sub-list.
141: if (start > (ls - 1)) {
142:
143: // Return nothing, outside of the range.
144: return new ArrayList();
145:
146: }
147:
148: if (rows > 0) {
149:
150: if ((start + rows) > (ls - 1)) {
151:
152: // Just return the rows starting at start...
153: // We return a new list to prevent issues with modifications...
154: return new ArrayList(objs.subList(start, ls));
155:
156: }
157:
158: // Here we return start + rows.
159: return new ArrayList(objs.subList(start, start + rows));
160:
161: } else {
162:
163: // Just ignore the rows...
164: return new ArrayList(objs.subList(start, ls));
165:
166: }
167:
168: }
169:
170: public void setStart(ValueExpression v) {
171:
172: this .start = v;
173:
174: }
175:
176: public void setRowsCount(ValueExpression v) {
177:
178: this.rowsCount = v;
179:
180: }
181:
182: }
|