/*
* Copyright (C) 2007 SQL Explorer Development Team
* http://sourceforge.net/projects/eclipsesql
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package net.sourceforge.sqlexplorer.parsers;
import java.sql.CallableStatement;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import net.sourceforge.sqlexplorer.parsers.Tokenizer.Token;
/**
* A named parameter
*
* @author John Spackman
*/
public class NamedParameter implements Comparable<NamedParameter> {
// Data Type of the parameter
public enum DataType {
INTEGER {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.INTEGER);
int intValue = 0;
if (param.value != null)
try {
intValue = Integer.parseInt(param.value.toString());
} catch(NumberFormatException e) {
}
stmt.setInt(columnIndex, intValue);
}
},
DECIMAL {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.DOUBLE);
double doubleValue = 0;
if (param.value != null)
try {
doubleValue = Double.parseDouble(param.value.toString());
} catch(NumberFormatException e) {
}
stmt.setDouble(columnIndex, doubleValue);
}
},
STRING {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.VARCHAR);
stmt.setString(columnIndex, param.value == null ? "" : param.value.toString());
}
},
DATE {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.DATE);
Date date = new Date(System.currentTimeMillis());
if (param.value != null)
try {
DateFormat df;
String formatName = null;
if (param.arguments != null && !param.arguments.isEmpty())
formatName = param.arguments.get(0).getUnquotedValue().toString().trim();
if (formatName == null || formatName.length() == 0)
df = DateFormat.getDateInstance();
else if (formatName.equalsIgnoreCase("short"))
df = DateFormat.getDateInstance(DateFormat.SHORT);
else if (formatName.equalsIgnoreCase("medium"))
df = DateFormat.getDateInstance(DateFormat.MEDIUM);
else if (formatName.equalsIgnoreCase("long"))
df = DateFormat.getDateInstance(DateFormat.LONG);
else
df = new SimpleDateFormat(formatName);
String value = param.value.toString();
java.util.Date newDt = df.parse(value);
date = new Date(newDt.getTime());
} catch(ParseException e) {
throw new SQLException(e.getMessage());
}
stmt.setDate(columnIndex, date);
}
},
TIME {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.TIME);
Date date = new Date(System.currentTimeMillis());
if (param.value != null)
try {
DateFormat df;
String formatName = null;
if (param.arguments != null && !param.arguments.isEmpty())
formatName = param.arguments.get(0).getUnquotedValue().toString().trim();
if (formatName == null || formatName.length() == 0)
df = DateFormat.getTimeInstance();
else if (formatName.equalsIgnoreCase("short"))
df = DateFormat.getTimeInstance(DateFormat.SHORT);
else if (formatName.equalsIgnoreCase("medium"))
df = DateFormat.getTimeInstance(DateFormat.MEDIUM);
else if (formatName.equalsIgnoreCase("long"))
df = DateFormat.getTimeInstance(DateFormat.LONG);
else
df = new SimpleDateFormat(formatName);
date = new Date(df.parse(param.value.toString()).getTime());
} catch(ParseException e) {
throw new SQLException(e.getMessage());
}
stmt.setDate(columnIndex, date);
}
},
DATETIME {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
if (param.isOutput())
stmt.registerOutParameter(columnIndex, Types.TIMESTAMP);
Date date = new Date(System.currentTimeMillis());
if (param.value != null)
try {
DateFormat df;
String formatName = null;
if (param.arguments != null && !param.arguments.isEmpty())
formatName = param.arguments.get(0).getUnquotedValue().toString().trim();
if (formatName == null || formatName.length() == 0)
df = DateFormat.getDateTimeInstance();
else if (formatName.equalsIgnoreCase("short"))
df = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
else if (formatName.equalsIgnoreCase("medium"))
df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
else if (formatName.equalsIgnoreCase("long"))
df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
else
df = new SimpleDateFormat(formatName);
date = new Date(df.parse(param.value.toString()).getTime());
} catch(ParseException e) {
throw new SQLException(e.getMessage());
}
stmt.setDate(columnIndex, date);
}
},
CURSOR {
@Override
public void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException {
throw new IllegalAccessError("Cursors are not supported by this database type");
}
};
public abstract void configureStatement(NamedParameter param, CallableStatement stmt, int columnIndex) throws SQLException;
};
// Directionality
public enum Direction { INPUT, OUTPUT, INOUT };
// The Token containing the structured comment which defined this
// named parameter; used to determine scope
private Token comment;
// Parameter name
private String name;
// Data Type of the parameter
private DataType dataType;
// IN, OUT, or both
private Direction direction;
// Arguments
private List<Token> arguments;
// Value of the parameter (for input parameters only)
private CharSequence value;
public NamedParameter(Token comment, String name, DataType dataType, Direction direction, List<Token> arguments, CharSequence value) {
super();
this.comment = comment;
this.name = name;
this.dataType = dataType;
this.direction = direction;
this.arguments = arguments;
this.value = value;
}
/**
* Configures the statement with this parameter, where the parameter is at a
* given ordinal index
* @param stmt
* @param param
* @param columnIndex
*/
public void configureStatement(CallableStatement stmt, int columnIndex) throws SQLException {
dataType.configureStatement(this, stmt, columnIndex);
}
/**
* Returns true if this parameter is an output (may also be an input)
* @return
*/
public boolean isOutput() {
return direction != Direction.INPUT;
}
/**
* Returns true if this parameter is an input (may also be an output)
* @return
*/
public boolean isInput() {
return direction != Direction.OUTPUT;
}
public Token getComment() {
return comment;
}
public DataType getDataType() {
return dataType;
}
public Direction getDirection() {
return direction;
}
public String getName() {
return name;
}
public CharSequence getValue() {
return value;
}
public int compareTo(NamedParameter that) {
return name.compareTo(that.name);
}
public String toString() {
return ":" + name + "[" + direction.toString().toLowerCase() + " " + dataType.toString().toLowerCase() + "] = " + (value == null ? "null" : ("\"" + value.toString() + "\""));
}
}