package au.gov.amsa.util.rx;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import rx.Observable.Operator;
import rx.Observer;
import rx.Subscriber;
import rx.observers.Subscribers;
public class OperatorWriteBytes implements Operator<String, byte[]> {
private static final int DEFAULT_BUFFER_SIZE = 8192;
private final OutputStream out;
private final boolean closeOnTerminate;
private final File file;
private final boolean append;
private final int bufferSize;
private final boolean createTempFile;
private OperatorWriteBytes(File file, boolean createTempFile,
boolean append, OutputStream out, boolean closeOnTerminate,
int bufferSize) {
this.file = file;
this.createTempFile = createTempFile;
this.append = append;
this.out = out;
this.closeOnTerminate = closeOnTerminate;
this.bufferSize = bufferSize;
}
public OperatorWriteBytes(File file, boolean append) {
this(file, false, append, null, true, DEFAULT_BUFFER_SIZE);
}
public OperatorWriteBytes(File file, boolean append, int bufferSize) {
this(file, false, append, null, true, bufferSize);
}
public OperatorWriteBytes() {
this(null, true, true, null, true, DEFAULT_BUFFER_SIZE);
}
public OperatorWriteBytes(int bufferSize) {
this(null, true, true, null, true, bufferSize);
}
public OperatorWriteBytes(OutputStream out, boolean closeOnTerminate) {
this(null, false, true, out, closeOnTerminate, DEFAULT_BUFFER_SIZE);
}
public OperatorWriteBytes(OutputStream out, boolean closeOnTerminate,
int bufferSize) {
this(null, false, true, out, closeOnTerminate, DEFAULT_BUFFER_SIZE);
}
@SuppressWarnings("resource")
@Override
public Subscriber<? super byte[]> call(
final Subscriber<? super String> child) {
// TODO prevent multiple active subscribers
final OutputStream o;
final File actualFile;
if (file != null || createTempFile)
try {
if (createTempFile)
actualFile = File.createTempFile(
OperatorWriteBytes.class.getName(), ".bin");
else
actualFile = file;
o = new FileOutputStream(actualFile, append);
} catch (IOException e) {
child.onError(e);
return Subscribers.empty();
}
else {
o = out;
actualFile = null;
}
final OutputStream os = new BufferedOutputStream(o, bufferSize);
final Subscriber<byte[]> parent = Subscribers
.from(new Observer<byte[]>() {
@Override
public void onCompleted() {
if (closeOnTerminate)
try {
os.close();
if (actualFile != null)
child.onNext(actualFile.getPath());
child.onCompleted();
} catch (IOException e) {
child.onError(e);
}
else
child.onCompleted();
}
@Override
public void onError(Throwable e) {
if (closeOnTerminate)
try {
os.close();
child.onError(e);
} catch (IOException e2) {
child.onError(new CompositeException(e, e2));
}
else
child.onError(e);
}
@Override
public void onNext(byte[] bytes) {
try {
os.write(bytes);
} catch (IOException e) {
child.onError(e);
}
}
});
child.add(parent);
return parent;
}
}