
ai.h2o.mojos.runtime.frame.MojoRowBuilder Maven / Gradle / Ivy
package ai.h2o.mojos.runtime.frame;
import java.util.Collection;
import java.util.Map;
/**
* The builder is used to build rows for a {@link MojoFrameBuilder}. Rows are constructed by adding values in String form to a builder
* instance. The rows can then be added to a MojoFrameBuilder by calling {@link MojoFrameBuilder#addRow(MojoRowBuilder)}.
* {@code MojoRowBuilder}s can be initialized in a "strict" mode, where an exception is thrown whenever there is an
* attempt to set a value to a column name that is not defined in the builder. Additionally, "strict" {@code MojoRowBuilder}s
* will throw an exception if there is an attempt to create a row without every column being set a value beforehand.
*/
public class MojoRowBuilder {
private final Map columnNamesMap;
private final MojoColumn.Type[] columnTypes;
private final Collection missingValues;
private final StringConverter[] stringConverters;
private final boolean strict;
private Object[] values;
private boolean[] setValues;
MojoRowBuilder(Map columnNamesMap, MojoColumn.Type[] columnTypes, Collection missingValues,
StringConverter[] stringConverters, boolean strict) {
this.columnNamesMap = columnNamesMap;
this.columnTypes = columnTypes;
this.missingValues = missingValues;
this.stringConverters = stringConverters;
this.strict = strict;
values = new Object[this.columnTypes.length];
setValues = new boolean[values.length];
}
/**
* Set a value to the position associated with column {@code name} in the row.
* If this row builder instance is in "strict" mode, an {@link IllegalArgumentException} is thrown if {@code name}
* is not found in this builder. Otherwise nothing happens.
*
* The {@code value} is specified as a string and the call will try to convert the value to
* actual column type.
*
* @param name The name of the column to where the value should be set
* @param value The value to be set
*/
public MojoRowBuilder setValue(String name, String value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setValue(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
/**
* Set a value to an index in the row
*
* @param idx The index where the value should be set
* @param value The value to be set
*/
public MojoRowBuilder setValue(int idx, String value) {
if (idx < 0 || idx >= values.length) {
throw new ArrayIndexOutOfBoundsException("Index " + idx + " is out the scope of this MojoRowBuilder.");
}
final Object convertedValue;
if (value != null) {
if (missingValues.contains(value)) {
convertedValue = null;
} else {
final MojoColumn.Type columnType = columnTypes[idx];
convertedValue = stringConverters[idx].convert(value, columnType);
}
} else {
convertedValue = null;
}
values[idx] = convertedValue;
setValues[idx] = true;
return this;
}
public MojoRowBuilder setBool(String name, Boolean value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setBool(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setChar(String name, Character value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setChar(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setByte(String name, Byte value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setByte(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setShort(String name, Short value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setShort(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setInt(String name, Integer value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setInt(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setLong(String name, Long value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setLong(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setFloat(String name, Float value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setFloat(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setDouble(String name, Double value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setDouble(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setString(String name, String value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setString(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setDate(String name, java.sql.Date value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setDate(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
public MojoRowBuilder setTimestamp(String name, java.sql.Timestamp value) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
setTimestamp(idx, value);
} else if (isStrict()) {
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
return this;
}
private MojoRowBuilder setJavaValue(int idx, Object value) {
if (idx < 0 || idx >= values.length) {
throw new ArrayIndexOutOfBoundsException("Index " + idx + " is out of the scope of this MojoRowBuilder");
}
values[idx] = columnTypes[idx].fromJavaClass(value);
setValues[idx] = true;
return this;
}
public MojoRowBuilder setBool(int idx, Boolean value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setByte(int idx, Byte value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setShort(int idx, Short value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setChar(int idx, Character value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setInt(int idx, Integer value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setLong(int idx, Long value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setFloat(int idx, Float value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setDouble(int idx, Double value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setString(int idx, String value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setDate(int idx, java.sql.Date value) {
return setJavaValue(idx, value);
}
public MojoRowBuilder setTimestamp(int idx, java.sql.Timestamp value) {
return setJavaValue(idx, value);
}
/**
* Set the entire row to `values`.
*
* The parameter `values` needs to contain actual object matching types of columns.
*
* @param values The array of values to be set into the row.
*/
public MojoRowBuilder setValues(Object[] values) {
if (values.length != this.values.length)
throw new IllegalArgumentException("Length of values argument does not match size of MojoRowBuilder! " +
"Expected: " + this.values.length + ", but got: " + values.length);
System.arraycopy(values, 0, this.values, 0, this.values.length);
return this;
}
MojoRow toMojoRow() {
if (isStrict()) {
for (int i = 0; i < setValues.length; i += 1) {
if (!setValues[i]) {
String indices = "[" + i;
for (int k = i + 1; k < setValues.length; k += 1) {
if (!setValues[k]) {
indices += ", " + k;
}
}
indices += ']';
throw new IllegalStateException("Columns at indices " + indices + " have not been set");
}
}
}
return new MojoRow(values);
}
/**
* Clear the state of the row builder
*/
public void clear() {
values = new Object[values.length];
setValues = new boolean[setValues.length];
}
/**
* Get the number values a row resulting from this builder would have
*
* @return The number of values
*/
public int size() {
return values.length;
}
/**
* Determine if this row builder is in "strict" mode.
* A "strict" row builder will throw an exception if a value is attempted to be set to a column whose name is not
* associated with an index. Additionally, {@link #toMojoRow()} will throw an exception unless all values have been
* set.
*
* @return {@code true} if this row builder instance is in "strict" mode; {@code false} otherwise.
*/
public boolean isStrict() {
return strict;
}
/**
* Determine whether the column associated with name {@code name} has had a value set.
*
* @param name The name of the column
* @return {@code true} if the column associated with name {@code name} has had a value set; {@code false} otherwise.
*/
public boolean isSet(String name) {
Integer idx = columnNamesMap.get(name);
if (idx != null) {
return isSet(idx);
}
throw new IllegalArgumentException("Column \"" + name + "\" does not exist is this MojoRowBuilder");
}
/**
* Determine whether the column at index {@code idx} has had a value set.
*
* @param idx The index of the column
* @return {@code true} if the column at index {@code idx} has had a value set; {@code false} otherwise.
*/
public boolean isSet(int idx) {
if (idx >= 0 && idx < size()) {
return setValues[idx];
}
throw new ArrayIndexOutOfBoundsException("Index " + idx + " is out of the scope of this MojoRowBuilder");
}
/**
* Determine if there is a column associated with name {@code name}.
*
* @param name
* @return {@code true} if there exists a column associated with name {@code name}; {@code false} otherwise.
*/
public boolean containsName(String name) {
return columnNamesMap.containsKey(name);
}
}
class MojoRow {
private Object[] values;
MojoRow(Object[] values) {
this.values = values;
}
public int size() {
return values.length;
}
Object[] getValues() {
return values;
}
}