package org.smoothbuild.db.hashed;
import static com.google.common.primitives.Ints.toByteArray;
import static org.smoothbuild.db.hashed.Hash.toPath;
import static org.smoothbuild.io.fs.base.PathState.NOTHING;
import java.io.IOException;
import java.io.OutputStream;
import org.smoothbuild.io.fs.base.FileSystem;
import org.smoothbuild.io.fs.base.Path;
import com.google.common.hash.HashCode;
import com.google.common.hash.Hasher;
public class Marshaller extends OutputStream {
private final FileSystem fileSystem;
private final Path rootPath;
private final Path tempPath;
private HashCode hash;
private final OutputStream outputStream;
private final Hasher hasher;
public Marshaller(FileSystem fileSystem, Path rootPath, Path tempPath, HashCode hash) {
this.fileSystem = fileSystem;
this.rootPath = rootPath;
this.tempPath = tempPath;
this.hash = hash;
this.hasher = Hash.newHasher();
this.outputStream = fileSystem.openOutputStream(tempPath);
}
public void writeHash(HashCode hash) {
write(hash.asBytes());
}
public void writeInt(int intValue) {
write(toByteArray(intValue));
}
public void write(int b) {
write(new byte[] { (byte) b });
}
public void write(byte b[]) {
write(b, 0, b.length);
}
public void write(byte bytes[], int off, int len) {
hasher.putBytes(bytes, off, len);
try {
outputStream.write(bytes, off, len);
} catch (IOException e) {
throw newHashedDbException(hash, e);
}
}
public void close() {
if (hash == null) {
hash = hasher.hash();
}
try {
outputStream.close();
} catch (IOException e) {
newHashedDbException(hash, e);
}
Path path = rootPath.append(toPath(hash));
if (fileSystem.pathState(path) == NOTHING) {
fileSystem.move(tempPath, path);
}
}
public HashCode hash() {
return hash;
}
private static HashedDbException newHashedDbException(HashCode hash, Throwable e) {
return new HashedDbException("IO error occurred while writing " + hash + " object.", e);
}
}