import java.util.*;
import java.util.zip.*;
import org.ibex.util.*;
+import java.sql.*;
/** a source of streams */
public interface Fountain {
public Stream getStream();
- public int getLength();
- public int getNumLines();
- /*
- public static interface Transformer {
- public Fountain transform(Fountain in);
-
- public static class Lift implements Fountain.Transformer {
- private final Stream.Transformer func;
- public Lift(Stream.Transformer func) { this.func = func; }
- public Fountain transform(final Fountain in) {
- return new Fountain() {
- public Stream getStream() {
- return func.transform(in.getStream()); } };
- }
- }
- }
- */
+ public long getLength();
+ public int getNumLines();
public static class File implements Fountain {
private final java.io.File file;
public File(java.io.File file) { this.file = file; }
public Stream getStream() { return new Stream(file); }
- public int getLength() { return (int)file.length(); }
+ public long getLength() { return (int)file.length(); }
public int getNumLines() { return Stream.countLines(getStream()); }
}
private final byte[] bytes;
private final int off;
private final int len;
+ protected ByteArray(String s) {
+ try {
+ byte[] bytes = s.getBytes("UTF-8");
+ this.bytes = bytes;
+ this.off = 0;
+ this.len = bytes.length;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
public ByteArray(byte[] bytes) { this(bytes, 0, bytes.length); }
public ByteArray(byte[] bytes, int off, int len) { this.bytes = bytes; this.off=off; this.len=len; }
public Stream getStream() { return new Stream(bytes, off, len); }
- public int getLength() { return len; }
+ public long getLength() { return len; }
public int getNumLines() { return Stream.countLines(getStream()); }
}
- public static class StringFountain implements Fountain {
- String s;
- public StringFountain(String s) { this.s = s; }
- public Stream getStream() { return new Stream(s); }
- public int getLength() { return s.length(); } // FIXME ENCODING ISSUES!!!!!
- public int getNumLines() { return Stream.countLines(getStream()); }
+
+ public static class StringFountain extends ByteArray {
+ public StringFountain(String s) { super(s); }
}
public static class Concatenate implements Fountain {
- Fountain f1, f2;
- public Concatenate(Fountain f1, Fountain f2) { this.f1 = f1; this.f2 = f2; }
- public Stream getStream() { return f1.getStream().appendStream(f2.getStream()); }
- public int getLength() { return f1.getLength()+f2.getLength(); }
- public int getNumLines() { return f1.getNumLines()+f2.getNumLines(); }
+ private Fountain[] founts;
+ public Concatenate(Fountain f1, Fountain f2) { this(new Fountain[] { f1, f2 }); }
+ public Concatenate(Fountain[] f) { this.founts = f; }
+ public Stream getStream() {
+ Stream ret = null;
+ for(int i=founts.length-1; i>=0; i--)
+ ret = ret==null ? founts[i].getStream() : founts[i].getStream().appendStream(ret);
+ return ret;
+ }
+ public long getLength() {
+ long ret = 0;
+ for(int i=0; i<founts.length; i++)
+ ret += founts[i].getLength();
+ return ret;
+ }
+ public int getNumLines() {
+ int ret = 0;
+ for(int i=0; i<founts.length; i++)
+ ret += founts[i].getNumLines();
+ return ret;
+ }
}
+ // FIXME: untested
+ // note: only one ResultSet is allowed per Statement
+ public static class DatabaseColumn implements Fountain {
+ private ResultSet rs;
+ private int row;
+ private int column;
+ public DatabaseColumn(ResultSet rs, int column) throws SQLException {
+ this(rs, column, rs.getRow());
+ }
+ public DatabaseColumn(ResultSet rs, int column, int row) throws SQLException {
+ this.rs = rs;
+ this.row = row;
+ this.column = column;
+ synchronized(rs) {
+ int type = rs.getType();
+ if ((type | ResultSet.TYPE_SCROLL_INSENSITIVE) == 0)
+ throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) requires a SCROLL_INSENSITIVE ResultSet");
+ if ((type | ResultSet.TYPE_FORWARD_ONLY) != 0)
+ throw new RuntimeException("Fountain.DatabaseColumn(ResultSet,int) cannot use TYPE_FORWARD_ONLY ResultSets");
+ }
+ // FIXME: do we want to check HOLD_CURSORS_OVER_COMMIT ?
+ }
+ private Blob getBlob() throws SQLException {
+ synchronized(rs) {
+ if (!rs.absolute(row))
+ throw new RuntimeException("resultset was unable to move to desired row");
+ return rs.getBlob(column);
+ }
+ }
+ public Stream getStream() {
+ try {
+ synchronized(rs) {
+ return new Stream(rs.getBinaryStream(column));
+ }
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+ public long getLength() {
+ try {
+ synchronized(rs) {
+ return getBlob().length();
+ }
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+ public int getNumLines() {
+ throw new RuntimeException("not implemented");
+ }
+ }
+
+
//public static class LazyCachingStreamFountain implements Fountain {
//}
+ /*
+ public static interface Transformer {
+ public Fountain transform(Fountain in);
+
+ public static class Lift implements Fountain.Transformer {
+ private final Stream.Transformer func;
+ public Lift(Stream.Transformer func) { this.func = func; }
+ public Fountain transform(final Fountain in) {
+ return new Fountain() {
+ public Stream getStream() {
+ return func.transform(in.getStream()); } };
+ }
+ }
+ }
+ */
+
+ public static class Util {
+ public static Fountain create(String s) { return new StringFountain(s); }
+ public static Fountain concat(Fountain[] f) { return new Concatenate(f); }
+ public static Fountain concat(Fountain f1, Fountain f2) {
+ return new Concatenate(f1, f2);
+ }
+ public static Fountain concat(Fountain f1, Fountain f2, Fountain f3) {
+ return new Concatenate(f1, new Concatenate(f2, f3));
+ }
+ }
}