001: package org.apache.ojb.broker.util;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import java.sql.ResultSet;
019: import java.sql.SQLException;
020:
021: import org.apache.commons.lang.StringUtils;
022:
023: /**
024: * Helper class for all SQL related stuff.
025: *
026: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel </a>
027: * @version $Id: SqlHelper.java,v 1.24.2.4 2005/12/21 22:27:47 tomdz Exp $
028: */
029: public class SqlHelper {
030: /** define the name of the pseudo column holding the class to be instantiated. */
031: public static final String OJB_CLASS_COLUMN = "OJB_CLAZZ";
032:
033: /**
034: * Helper Class for a split column <br>
035: * ie: sum (distinct amount) as theAmount
036: *
037: * <pre>
038: * prefix = 'sum (distinct '
039: * column = 'amount'
040: * suffix = ') as theAmount'
041: * </pre>
042: */
043: public static final class PathInfo {
044: public String column;
045: public String prefix;
046: public String suffix;
047: public final String path; //original Path
048:
049: PathInfo(String aPath, String aPrefix, String aColumn,
050: String aSuffix) {
051: path = aPath;
052: column = aColumn;
053: prefix = aPrefix;
054: suffix = aSuffix;
055: }
056: }
057:
058: /**
059: * remove functions and () from path <br>
060: * ie: avg(amount) -> amount <br>
061: * ie: sum (accounts.amount) -> accounts.amount <br>
062: * ie: count(distinct id) as theCount-> id <br>
063: *
064: * @param aPath
065: * the path to the attribute
066: */
067: public static String cleanPath(String aPath) {
068: return splitPath(aPath).column;
069: }
070:
071: /**
072: * Split a path into column , prefix and suffix, the prefix contains all
073: * info up to the column <br>
074: * ie: avg(amount) -> amount , avg( , )<br>
075: * ie: sum (accounts.amount) as theSum -> accounts.amount , sum( , ) as
076: * theSum <br>
077: * ie: count( distinct id ) as bla -> id , count(distinct , ) as bla <br>
078: * Supports simple expressions ie: price * 1.05
079: *
080: * TODO: cannot resolve multiple attributes in expression
081: * ie: price - bonus
082: *
083: * @param aPath
084: * @return PathInfo
085: */
086: public static PathInfo splitPath(String aPath) {
087: String prefix = null;
088: String suffix = null;
089: String colName = aPath;
090:
091: if (aPath == null) {
092: return new PathInfo(null, null, null, null);
093: }
094:
095: // ignore leading ( and trailing ) ie: sum(avg(col1))
096: int braceBegin = aPath.lastIndexOf("(");
097: int braceEnd = aPath.indexOf(")");
098: int opPos = StringUtils.indexOfAny(aPath, "+-/*");
099:
100: if (braceBegin >= 0 && braceEnd >= 0 && braceEnd > braceBegin) {
101: int colBegin;
102: int colEnd;
103: String betweenBraces;
104:
105: betweenBraces = aPath.substring(braceBegin + 1, braceEnd)
106: .trim();
107: // look for ie 'distinct name'
108: colBegin = betweenBraces.indexOf(" ");
109: // look for multiarg function like to_char(col,'format_mask')
110: colEnd = betweenBraces.indexOf(",");
111: colEnd = colEnd > 0 ? colEnd : betweenBraces.length();
112: prefix = aPath.substring(0, braceBegin + 1)
113: + betweenBraces.substring(0, colBegin + 1);
114: colName = betweenBraces.substring(colBegin + 1, colEnd);
115: suffix = betweenBraces.substring(colEnd)
116: + aPath.substring(braceEnd);
117: } else if (opPos >= 0) {
118: colName = aPath.substring(0, opPos).trim();
119: suffix = aPath.substring(opPos);
120: }
121:
122: return new PathInfo(aPath, prefix, colName.trim(), suffix);
123: }
124:
125: /**
126: * Returns the name of the class to be instantiated.
127: * @param rs the Resultset
128: * @return null if the column is not available
129: */
130: public static String getOjbClassName(ResultSet rs) {
131: try {
132: return rs.getString(OJB_CLASS_COLUMN);
133: } catch (SQLException e) {
134: return null;
135: }
136: }
137:
138: }
|