package org.smoothbuild.lang.value;
import static java.util.stream.Collectors.joining;
import static java.util.stream.StreamSupport.stream;
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
import org.smoothbuild.db.hashed.HashedDb;
import org.smoothbuild.db.hashed.Marshaller;
import org.smoothbuild.db.hashed.Unmarshaller;
import org.smoothbuild.lang.type.ArrayType;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.HashCode;
public class Array<T extends Value> extends Value implements Iterable<T> {
private final Function<HashCode, T> valueConstructor;
private final HashedDb hashedDb;
public Array(HashCode hash, ArrayType arrayType, Function<HashCode, T> valueConstructor,
HashedDb hashedDb) {
super(arrayType, hash);
this.valueConstructor = valueConstructor;
this.hashedDb = hashedDb;
}
public static <T extends Value> Array<T> storeArrayInDb(List<? extends Value> elements,
ArrayType arrayType, Function<HashCode, T> valueConstructor, HashedDb hashedDb) {
Marshaller marshaller = hashedDb.newMarshaller();
for (Value element : elements) {
marshaller.writeHash(element.hash());
}
marshaller.close();
return new Array<T>(marshaller.hash(), arrayType, valueConstructor, hashedDb);
}
public Iterator<T> iterator() {
try (Unmarshaller unmarshaller = hashedDb.newUnmarshaller(hash())) {
ImmutableList.Builder<T> builder = ImmutableList.builder();
HashCode elementHash = null;
while ((elementHash = unmarshaller.tryReadHash()) != null) {
builder.add(valueConstructor.apply(elementHash));
}
return builder.build().iterator();
}
}
public String toString() {
return "[" + stream(this.spliterator(), false).map(Object::toString).collect(joining(", "))
+ "]";
}
}