package railo.runtime.type.sql;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import railo.commons.io.IOUtil;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.op.Caster;
/**
* The representation (mapping) in the Java <sup><small>TM </small> </sup>
* programming language of an SQL <code>CLOB</code> value. An SQL
* <code>CLOB</code> is a built-in type that stores a Character Large Object
* as a column value in a row of a database table. By default drivers implement
* <code>Clob</code> using an SQL <code>locator(CLOB)</code>, which means
* that a <code>Clob</code> object contains a logical pointer to the SQL
* <code>CLOB</code> data rather than the data itself. A <code>Clob</code>
* object is valid for the duration of the transaction in which is was created.
* <p>
* Methods in the interfaces {@link DriverResultSet},{@link CallableStatement},
* and {@link PreparedStatement}, such as <code>getClob</code> and
* <code>setClob</code> allow a programmer to access an SQL <code>CLOB</code>
* value. The <code>Clob</code> interface provides methods for getting the
* length of an SQL <code>CLOB</code> (Character Large Object) value, for
* materializing a <code>CLOB</code> value on the client, and for determining
* the position of a pattern of bytes within a <code>CLOB</code> value. In
* addition, this interface has methods for updating a <code>CLOB</code>
* value.
*/
public final class ClobImpl implements java.sql.Clob, Serializable {
/**
* cast given value to a clob
* @param value
* @return clob
* @throws PageException
*/
public static Clob toClob(Object value) throws PageException {
if(value instanceof Clob) return (Clob)value;
else if(value instanceof char[])
return toClob(new String((char[])value));
else if(value instanceof Reader) {
StringWriter sw=new StringWriter();
try {
IOUtil.copy((Reader)value,sw,false,true);
}
catch (IOException e) {
throw ExpressionException.newInstance(e);
}
return toClob(sw.toString());
}
return toClob(Caster.toString(value));
}
public static Clob toClob(String value) {
return new ClobImpl(value);
}
/** The data represented as a string of this <code>CLOB</code> */
private String stringData = null;
/**
* Creates a new <code>Clob</code> instance.
*
* @param data a <code>String</code> of character data
*/
private ClobImpl(String data) {
stringData = data;
}
/**
* Returns the size of the <code>CLOB</code> value designated by this
* <code>Clob</code> object
*
* @return length of the <code>CLOB</code> value that this <code>clob</code>
* represents
* @exception SQLException if there is an error accessing the length of the
* <code>CLOB</code>
*/
public long length() throws SQLException {
return stringData.length();
}
/**
* Retrieves the <code>CLOB</code> value designated by this
* <code>Clob</code> instance as a stream.
*
* @return a stream containing the <code>CLOB</code> data
* @exception SQLException if there is an error accessing the
* <code>CLOB</code> value
*/
public java.io.InputStream getAsciiStream() throws SQLException {
return new ByteArrayInputStream(stringData.getBytes());
}
/**
* Materializes the <code>CLOB</code> value designated by this <Code>object
* as a stream of Unicode character.
*
* @return A reader object with all the data in the <code>CLOB</code> value
* designated by this clob object as unicode characters.
* @exception SQLException if there is an error accessing the
* <code>CLOB</code> value
*/
public java.io.Reader getCharacterStream() throws SQLException {
return new StringReader(stringData);
}
public Reader getCharacterStream(long pos, long len) {
return new StringReader(stringData.substring((int)pos, (int)len));
}
/**
* Returns a copy of the portion of the <code>CLOB</code> value represented
* by this <code>CLOB</code> object that starts at position <i>position </i>
* and has ip to <i>length </i> consecutive characters.
*
* @param pos the position where to get the substring from
* @param length the length of the substring
* @return the substring
* @exception SQLException if there is an error accessing the
* <code>CLOB</code>
*/
public String getSubString(long pos, int length) throws SQLException {
if (length > stringData.length())
throw new SQLException("Clob contains only " + stringData.length()
+ " characters (asking for " + length + ").");
return stringData.substring((int) pos-1, length);
}
/**
* Retrieves the character position at which the specified string
* <code>searchstr</code> begins within the <code>CLOB</code> value that
* this <code>Clob</code> object represents. The search for
* <code>searchstr</code> begins at position <code>start</code>.
*
* @param searchstr the byte array for which to search
* @param start the position at which to begin searching; the first position
* is 1
* @return the position at which the pattern appears, else -1
* @exception SQLException if there is an error accessing the
* <code>CLOB</code>
*/
public long position(String searchstr, long start) throws SQLException {
return stringData.indexOf(searchstr, (int) start);
}
/**
* Retrieves the character position at which the specified <code>Clob</code>
* object <code>searchstr</code> begins within the <code>CLOB</code> value
* that this <code>Clob</code> object represents. The search for
* <code>searchstr</code> begins at position <code>start</code>.
*
* @param searchstr the byte array for which to search
* @param start the position at which to begin searching; the first position
* is 1
* @return the position at which the pattern appears, else -1
* @exception SQLException if there is an error accessing the
* <code>CLOB</code>
*/
public long position(java.sql.Clob searchstr, long start) throws SQLException {
return position(searchstr.getSubString(0, (int) searchstr.length()),
(int) start);
}
// -------------------------- JDBC 3.0 -----------------------------------
/**
* Retrieves a stream to be used to write Ascii characters to the CLOB value
* that this Clob object represents, starting at position pos.
*
* @param pos the position where to start the stream
* @return the ascii outputstream to this <code>clob</code> object
* @throws SQLException if there is an error accessing the <code>clob</code>
*/
public OutputStream setAsciiStream(long pos) throws SQLException {
// TODO impl.
throw new SQLException("JDBC 3.0 Method setAsciiStream not implemented");
}
/**
* Retrieves a stream to be used to write a stream of Unicode characters to
* the CLOB value that this Clob object represents, at position pos.
*
* @param pos the position where to start the writer
* @return the writer to this <code>clob</code> object
* @throws SQLException if there is an error accessing the <code>clob</code>
*/
public Writer setCharacterStream(long pos) throws SQLException {
// TODO impl.
throw new SQLException("JDBC 3.0 Method setCharacterStream not implemented");
}
/**
* Writes the given Java String to the CLOB value that this Clob object
* designates at the position pos.
*
* @param pos the position where to set the string
* @param str string to insert in the <code>clob</code>
* @return return value
* @throws SQLException if there is an error accessing the <code>clob</code>
*/
public int setString(long pos, String str) throws SQLException {
// TODO impl.
throw new SQLException("JDBC 3.0 Method setString not implemented");
}
/**
* Writes len characters of str, starting at character offset, to the CLOB
* value that this Clob represents.
*
* @param pos the position
* @param str the string
* @param offset the offset
* @param len the length
* @return return value
* @throws SQLException if there is an error accessing the <code>clob</code>
*/
public int setString(long pos, String str, int offset, int len) throws SQLException{
// TODO impl.
throw new SQLException("JDBC 3.0 Method setString not implemented");
}
/**
* Truncates the CLOB value that this Clob designates to have a length of len
* characters.
*
* @param len the length
* @throws SQLException if there is an error accessing the <code>clob</code>
*/
public void truncate(long len) throws SQLException
{
// TODO impl.
throw new SQLException("JDBC 3.0 Method truncate not implemented");
}
@Override
public String toString() {
return stringData;
}
public void free() {
stringData="";
}
}