001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.cmp.jdbc.metadata;
023:
024: import java.io.IOException;
025: import java.io.StringReader;
026: import java.util.ArrayList;
027:
028: import org.jboss.deployment.DeploymentException;
029: import org.jboss.metadata.MetaData;
030: import org.w3c.dom.Element;
031:
032: public final class JDBCFunctionMappingMetaData {
033: private final String functionName;
034: private String[] sqlChunks;
035: private int[] parameters;
036:
037: public JDBCFunctionMappingMetaData(String functionName,
038: String[] sqlChunks, int[] parameters) {
039: this .functionName = functionName;
040: this .sqlChunks = sqlChunks;
041: this .parameters = parameters;
042: }
043:
044: public JDBCFunctionMappingMetaData(Element element)
045: throws DeploymentException {
046: functionName = MetaData.getUniqueChildContent(element,
047: "function-name");
048:
049: String sql = MetaData.getUniqueChildContent(element,
050: "function-sql");
051: initFromString(sql);
052: }
053:
054: public JDBCFunctionMappingMetaData(String functionName, String sql)
055: throws DeploymentException {
056: this .functionName = functionName;
057: initFromString(sql);
058: }
059:
060: private void initFromString(String sql) throws DeploymentException {
061: ArrayList chunkList = new ArrayList();
062: ArrayList parameterList = new ArrayList();
063:
064: // add a dummy chunk so we can be assured that the sql started with chunk before a number
065: if (sql.charAt(0) == '?') {
066: chunkList.add("");
067: }
068: // break the sql into chunks and parameters
069: StringBuffer chunk = new StringBuffer();
070: StringReader reader = new StringReader(sql);
071: try {
072: for (int c = reader.read(); c >= 0; c = reader.read()) {
073: if (c != '?') {
074: chunk.append((char) c);
075: } else {
076: chunkList.add(chunk.toString());
077: chunk = new StringBuffer();
078:
079: // read the number
080: StringBuffer number = new StringBuffer();
081: for (int digit = reader.read(); digit >= 0; digit = reader
082: .read()) {
083: if (Character.isDigit((char) digit)) {
084: number.append((char) digit);
085: } else {
086: if (digit >= 0) {
087: chunk.append((char) digit);
088: }
089: break;
090: }
091: }
092: if (number.length() == 0) {
093: throw new DeploymentException(
094: "Invalid parameter in function-sql: "
095: + sql);
096: }
097: Integer parameter;
098: try {
099: parameter = new Integer(number.toString());
100: } catch (NumberFormatException e) {
101: throw new DeploymentException(
102: "Invalid parameter number in function-sql: number="
103: + number + " sql=" + sql);
104: }
105: parameterList.add(parameter);
106: }
107: }
108: } catch (IOException e) {
109: // will never happen because io is in memory, but required by the interface
110: throw new DeploymentException(
111: "Error parsing function-sql: " + sql);
112: }
113: chunkList.add(chunk.toString());
114:
115: // save out the chunks
116: sqlChunks = new String[chunkList.size()];
117: chunkList.toArray(sqlChunks);
118:
119: // save out the parameter order
120: parameters = new int[parameterList.size()];
121: for (int i = 0; i < parameters.length; i++) {
122: parameters[i] = ((Integer) parameterList.get(i)).intValue() - 1;
123: }
124: }
125:
126: public String getFunctionName() {
127: return functionName;
128: }
129:
130: public StringBuffer getFunctionSql(Object[] args, StringBuffer buf) {
131: for (int i = 0; i < sqlChunks.length; i++) {
132: if (i < parameters.length) {
133: // the logic is that if there is a parameter
134: // than append its chunck unless the parameter is null
135: // FIXME: I am not sure it's ok for any kind of template.
136: Object arg = args[parameters[i]];
137: if (arg != null) {
138: buf.append(sqlChunks[i]);
139: buf.append(arg);
140: }
141: } else {
142: // this is tail
143: buf.append(sqlChunks[i]);
144: }
145: }
146: return buf;
147: }
148: }
|