package water.rapids.ast.prims.assign; import water.Iced; import water.fvec.Chunk; import water.fvec.Vec; import java.util.UUID; public class AstRecAsgnHelper { /** * Generic abstraction over Chunk setter methods. */ public static abstract class ValueSetter extends Iced<ValueSetter> { /** * Sets a value (possibly a constant) to a position of the Chunk. * @param idx Chunk-local index */ public abstract void setValue(Chunk chk, int idx); /** * Sets a value (possibly a constant) to a given index of a Vec. * @param vec Vec * @param idx absolute index */ public abstract void setValue(Vec vec, long idx); } /** * Create an instance of ValueSetter for a given scalar value. * It creates setter of the appropriate type based on the type of the underlying Vec. * @param v Vec * @param value scalar value * @return instance of ValueSetter */ public static ValueSetter createValueSetter(Vec v, Object value) { if (value == null) { return new NAValueSetter(); } switch (v.get_type()) { case Vec.T_CAT: return new CatValueSetter(v.domain(), value); case Vec.T_NUM: case Vec.T_TIME: return new NumValueSetter(value); case Vec.T_STR: return new StrValueSetter(value); case Vec.T_UUID: return new UUIDValueSetter(value); default: throw new IllegalArgumentException("Cannot create ValueSetter for a Vec of type = " + v.get_type_str()); } } private static class NAValueSetter extends ValueSetter { public NAValueSetter() {} // for Externalizable @Override public void setValue(Chunk chk, int idx) { chk.setNA(idx); } @Override public void setValue(Vec vec, long idx) { vec.setNA(idx); } } private static class CatValueSetter extends ValueSetter { private int _val; public CatValueSetter() {} // for Externalizable private CatValueSetter(String[] domain, Object val) { if (! (val instanceof String)) { throw new IllegalArgumentException("Value needs to be categorical, value = " + val); } int factorIdx = -1; for (int i = 0; i < domain.length; i++) if (val.equals(domain[i])) { factorIdx = i; break; } if (factorIdx == -1) throw new IllegalArgumentException("Value is not in the domain of the Vec, value = " + val); _val = factorIdx; } @Override public void setValue(Chunk chk, int idx) { chk.set(idx, _val); } @Override public void setValue(Vec vec, long idx) { vec.set(idx, (double) _val); } } private static class NumValueSetter extends ValueSetter { private double _val; public NumValueSetter() {} // for Externalizable private NumValueSetter(Object val) { if (! (val instanceof Number)) { throw new IllegalArgumentException("Value needs to be numeric, value = " + val); } _val = ((Number) val).doubleValue(); } @Override public void setValue(Chunk chk, int idx) { chk.set(idx, _val); } @Override public void setValue(Vec vec, long idx) { vec.set(idx, _val); } } private static class StrValueSetter extends ValueSetter { private String _val; public StrValueSetter() {} // for Externalizable private StrValueSetter(Object val) { if (! (val instanceof String)) { throw new IllegalArgumentException("Value needs to be string, value = " + val); } _val = (String) val; } @Override public void setValue(Chunk chk, int idx) { chk.set(idx, _val); } @Override public void setValue(Vec vec, long idx) { vec.set(idx, _val); } } private static class UUIDValueSetter extends ValueSetter { private UUID _val; public UUIDValueSetter() {} // for Externalizable private UUIDValueSetter(Object val) { if (val instanceof String) { val = UUID.fromString((String) val); } else if (! (val instanceof UUID)) { throw new IllegalArgumentException("Value needs to be an UUID, value = " + val); } _val = (UUID) val; } @Override public void setValue(Chunk chk, int idx) { chk.set(idx, _val); } @Override public void setValue(Vec vec, long idx) { vec.set(idx, _val); } } }