001: /*
002: * $Id: DateAddFunction.java,v 1.12 2005/05/02 22:28:41 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2005 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.functions;
042:
043: import java.sql.Timestamp;
044: import java.util.Calendar;
045:
046: import org.axiondb.AxionException;
047: import org.axiondb.DataType;
048: import org.axiondb.FunctionFactory;
049: import org.axiondb.RowDecorator;
050: import org.axiondb.types.IntegerType;
051: import org.axiondb.types.StringType;
052: import org.axiondb.types.TimestampType;
053: import org.axiondb.util.DateTimeUtils;
054:
055: /**
056: * Syntax: DateAdd(interval_type, interval, timestamp)
057: *
058: * @version $Revision: 1.12 $ $Date: 2005/05/02 22:28:41 $
059: * @author Rupesh Ramachandran
060: * @author Ritesh Adval
061: */
062: public class DateAddFunction extends BaseFunction implements
063: ScalarFunction, FunctionFactory {
064: /** Creates a new instance of Class */
065: public DateAddFunction() {
066: super ("DATEADD");
067: }
068:
069: public ConcreteFunction makeNewInstance() {
070: return new DateAddFunction();
071: }
072:
073: /** {@link DataType} */
074: public DataType getDataType() {
075: return RETURN_TYPE;
076: }
077:
078: /**
079: * Returns new Timestamp which is (timestamp + interval) where interval is integer
080: * units of interval_type. Valid interval types are {day, month, year, second,
081: * millisecond, minute, hour, week, quarter}
082: */
083: public Object evaluate(RowDecorator row) throws AxionException {
084: Timestamp timestamp = null;
085: int interval = -1;
086:
087: // Get 'interval_type'
088: int intervalType = DateTimeUtils
089: .labelToCode((String) (STRING_TYPE.convert(getArgument(
090: 0).evaluate(row))));
091:
092: // Get 'interval'
093: Object val = getArgument(1).evaluate(row);
094: if (null == val) {
095: return null;
096: } else {
097: interval = ((Integer) INT_TYPE.convert(val)).intValue();
098: }
099:
100: // Get 'timestamp'
101: Object val2 = getArgument(2).evaluate(row);
102: if (val2 == null) {
103: return null;
104: } else {
105: timestamp = (Timestamp) RETURN_TYPE.convert(val2);
106: }
107:
108: return calculateDateAdd(intervalType, interval, timestamp);
109: }
110:
111: /**
112: * Calculates the addition of an interval of a given type to given date.
113: *
114: * @param intervalType type of interval value ex- DAY, MONTH etc
115: * @param interval value of the interval
116: * @param t timestamp to which interval value needs to be added
117: * @return the resultant timestamp after adding given interval of given type
118: */
119: private Timestamp calculateDateAdd(int intervalType, int interval,
120: Timestamp t) {
121: Calendar c = Calendar.getInstance(TimestampType.getTimeZone());
122: c.setTimeInMillis(t.getTime());
123:
124: switch (intervalType) {
125: default:
126: case DateTimeUtils.MILLISECOND:
127: return addMillisecondsTo(c, interval);
128: case DateTimeUtils.SECOND:
129: return addSecondsTo(c, interval);
130: case DateTimeUtils.MINUTE:
131: return addMinutesTo(c, interval);
132: case DateTimeUtils.HOUR:
133: return addHoursTo(c, interval);
134: case DateTimeUtils.DAY:
135: return addDaysTo(c, interval);
136: case DateTimeUtils.WEEK:
137: return addWeeksTo(c, interval);
138: case DateTimeUtils.MONTH:
139: return addMonthsTo(c, interval);
140: case DateTimeUtils.QUARTER:
141: return addQuartersTo(c, interval);
142: case DateTimeUtils.YEAR:
143: return addYearsTo(c, interval);
144: }
145: }
146:
147: /**
148: * Adds millisecond to a date represented by Calendar object.
149: *
150: * @param c Calendar object representing a date
151: * @param milliseconds milliseconds to add
152: * @return date after adding milliseconds
153: */
154: private Timestamp addMillisecondsTo(Calendar c, int milliseconds) {
155: c.add(Calendar.MILLISECOND, milliseconds);
156: return new Timestamp(c.getTimeInMillis());
157: }
158:
159: /**
160: * Adds seconds to a date represented by Calendar object.
161: *
162: * @param c Calendar object representing a date
163: * @param seconds seconds to add
164: * @return date after adding seconds
165: */
166: private Timestamp addSecondsTo(Calendar c, int seconds) {
167: c.add(Calendar.SECOND, seconds);
168: return new Timestamp(c.getTimeInMillis());
169: }
170:
171: /**
172: * Adds minutes to a date represented by Calendar object.
173: *
174: * @param c Calendar object representing a date
175: * @param minutes minutes to add
176: * @return date after adding minutes
177: */
178: private Timestamp addMinutesTo(Calendar c, int minutes) {
179: c.add(Calendar.MINUTE, minutes);
180: return new Timestamp(c.getTimeInMillis());
181: }
182:
183: /**
184: * Adds hours to a date represented by Calendar object.
185: *
186: * @param c Calendar object representing a date
187: * @param hours hours to add
188: * @return date after adding hours
189: */
190: private Timestamp addHoursTo(Calendar c, int hours) {
191: c.add(Calendar.HOUR, hours);
192: return new Timestamp(c.getTimeInMillis());
193: }
194:
195: /**
196: * Adds days to a date represented by Calendar object.
197: *
198: * @param c Calendar object representing a date
199: * @param days days to add
200: * @return date after adding days
201: */
202: private Timestamp addDaysTo(Calendar c, int days) {
203: c.add(Calendar.DAY_OF_YEAR, days);
204: return new Timestamp(c.getTimeInMillis());
205: }
206:
207: /**
208: * Adds weeks to a date represented by Calendar object.
209: *
210: * @param c Calendar object representing a date
211: * @param weeks weeks to add
212: * @return date after adding weeks
213: */
214: private Timestamp addWeeksTo(Calendar c, int weeks) {
215: c.add(Calendar.WEEK_OF_YEAR, weeks);
216: return new Timestamp(c.getTimeInMillis());
217: }
218:
219: /**
220: * Adds months to a date represented by Calendar object.
221: *
222: * @param c Calendar object representing a date
223: * @param months months to add
224: * @return date after adding months
225: */
226: private Timestamp addMonthsTo(Calendar c, int months) {
227: c.add(Calendar.MONTH, months);
228: return new Timestamp(c.getTimeInMillis());
229: }
230:
231: /**
232: * Adds quarters to a date represented by Calendar object.
233: *
234: * @param c Calendar object representing a date
235: * @param quarters quarters to add
236: * @return date after adding quarters
237: */
238: private Timestamp addQuartersTo(Calendar c, int quarters) {
239: return addMonthsTo(c, quarters * 3);
240: }
241:
242: /**
243: * Adds years to a date represented by Calendar object.
244: *
245: * @param c Calendar object representing a date
246: * @param years years to add
247: * @return date after adding years
248: */
249: private Timestamp addYearsTo(Calendar c, int years) {
250: c.add(Calendar.YEAR, years);
251: return new Timestamp(c.getTimeInMillis());
252: }
253:
254: /**
255: * @see org.axiondb.functions.BaseFunction#isValid
256: */
257: public boolean isValid() {
258: return getArgumentCount() == 3;
259: }
260:
261: private static final DataType RETURN_TYPE = new TimestampType();
262: private static final DataType STRING_TYPE = new StringType();
263: private static final DataType INT_TYPE = new IntegerType();
264: }
|