001: /*
002: * $Id: SubstringFunction.java,v 1.10 2005/05/10 00:15:21 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 org.axiondb.AxionException;
044: import org.axiondb.DataType;
045: import org.axiondb.FunctionFactory;
046: import org.axiondb.RowDecorator;
047: import org.axiondb.Selectable;
048: import org.axiondb.types.IntegerType;
049: import org.axiondb.types.StringType;
050:
051: /**
052: * Syntax: SUBSTRING(str, m [,n]) -- m is one(1) based index.)
053: *
054: * @version $Revision: 1.10 $ $Date: 2005/05/10 00:15:21 $
055: * @author Sudhendra Seshachala
056: * @author Ahimanikya Satapathy
057: * @author Rupesh Ramachandran
058: */
059: public class SubstringFunction extends BaseFunction implements
060: ScalarFunction, FunctionFactory {
061:
062: /** Creates a new instance of Class */
063: public SubstringFunction() {
064: super ("SUBSTRING");
065: }
066:
067: public ConcreteFunction makeNewInstance() {
068: return new SubstringFunction();
069: }
070:
071: /** {@link StringType} */
072: public DataType getDataType() {
073: return RETURN_TYPE;
074: }
075:
076: /**
077: * Returns substring of str, beginning at character m, n characters long.
078: * <p>
079: * <li>If m is 0, it is treated as 1. If m is positive, it counts from the beginning
080: * of str to find the first character. If m is negative, it counts backwards from the
081: * end of str.
082: * <li>If n is omitted, it returns all characters to the end of str. If n is less
083: * than 1, a null is returned.
084: * <li>Floating-point numbers passed as arguments to substr are automatically
085: * converted to integers.
086: * <li>If m greater than length of str, return null. If m+n is bigger than length of
087: * str, ignore n. if str is null, return null.
088: */
089: public Object evaluate(RowDecorator row) throws AxionException {
090: int m = 0, n = 0;
091:
092: Object sel = getArgument(0).evaluate(row);
093: String str = (String) RETURN_TYPE.convert(sel);
094: // if current str is null, then return is also null
095: if (str == null) {
096: return null;
097: }
098: int strLen = str.length();
099:
100: // Get 'm'
101: Selectable sel1 = getArgument(1);
102: Object val1 = sel1.evaluate(row);
103: Integer int1 = (Integer) (INT_TYPE.convert(val1));
104: m = int1.intValue();
105: if (m < 0) {
106: m = strLen + m; // if -ve, count backwards from strLen
107: } else if (m != 0) {
108: m = m - 1; // if +ve, convert to 0-based index
109: }
110:
111: // if m == 0, then leave as 0 (1 in 0-based index)
112: // if m is too big, return null else IndexOutOfBound
113: if (m > strLen) {
114: return null;
115: }
116:
117: // Get 'n'
118: if (getArgumentCount() == 3) {
119: Selectable sel2 = getArgument(2);
120: Object val2 = sel2.evaluate(row);
121:
122: Integer int2 = (Integer) (INT_TYPE.convert(val2));
123: n = int2.intValue();
124: if (n < 1) {
125: return null;
126: }
127:
128: // if n is too big, ignore it
129: // otherwise IndexOutOfBound exception
130: if (n > (strLen - m)) {
131: n = strLen - m;
132: }
133: }
134:
135: if (getArgumentCount() == 3) {
136: return str.substring(m, n + m);
137: } else {
138: return str.substring(m);
139: }
140: }
141:
142: public boolean isValid() {
143: return (getArgumentCount() >= 2);
144: }
145:
146: private static final DataType RETURN_TYPE = new StringType();
147: private static final DataType INT_TYPE = new IntegerType();
148:
149: }
|