public record DataRow()

in baremaps-calcite/src/main/java/org/apache/baremaps/calcite/data/DataRow.java [26:160]


public record DataRow(DataTableSchema schema, List<Object> values) {

  /**
   * Constructs a row with validation.
   *
   * @param schema the schema
   * @param values the values
   * @throws NullPointerException if schema or values is null
   * @throws IllegalArgumentException if values size doesn't match schema columns
   */
  public DataRow {
    Objects.requireNonNull(schema, "Schema cannot be null");
    Objects.requireNonNull(values, "Values cannot be null");

    if (values.size() != schema.columns().size()) {
      throw new IllegalArgumentException(
          "Number of values (" + values.size() + ") doesn't match number of columns ("
              + schema.columns().size() + ")");
    }

    // Make a defensive copy to ensure immutability
    values = List.copyOf(values);
  }

  /**
   * Gets the value of the specified column.
   *
   * @param column the column name
   * @return the value
   * @throws IllegalArgumentException if the column is not found
   */
  public Object get(String column) {
    Objects.requireNonNull(column, "Column name cannot be null");

    // Use the schema's method to get column index for better performance
    int index = schema.getColumnIndex(column);
    return values.get(index);
  }

  /**
   * Gets the value at the specified index.
   *
   * @param index the index
   * @return the value
   * @throws IndexOutOfBoundsException if the index is out of bounds
   */
  public Object get(int index) {
    if (index < 0 || index >= values.size()) {
      throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + values.size());
    }
    return values.get(index);
  }

  /**
   * Creates a new row with the specified column set to the given value.
   *
   * @param column the column name
   * @param value the value
   * @return a new row with the updated value
   * @throws IllegalArgumentException if the column is not found
   */
  public DataRow with(String column, Object value) {
    Objects.requireNonNull(column, "Column name cannot be null");

    int index = schema.getColumnIndex(column);
    return with(index, value);
  }

  /**
   * Creates a new row with the value at the specified index set to the given value.
   *
   * @param index the index
   * @param value the value
   * @return a new row with the updated value
   * @throws IndexOutOfBoundsException if the index is out of bounds
   */
  public DataRow with(int index, Object value) {
    if (index < 0 || index >= values.size()) {
      throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + values.size());
    }

    // Validate value against column type if value is not null
    if (value != null) {
      DataColumn column = schema.columns().get(index);
      validateValue(column, value);
    }

    // Create a new list with the updated value
    var newValues = new java.util.ArrayList<>(values);
    newValues.set(index, value);
    return new DataRow(schema, newValues);
  }

  /**
   * Validates that the value is compatible with the column.
   *
   * @param column the column
   * @param value the value
   * @throws IllegalArgumentException if the value is not compatible
   */
  private void validateValue(DataColumn column, Object value) {
    // Skip validation for null values
    if (value == null) {
      if (column.isRequired()) {
        throw new IllegalArgumentException(
            "Column " + column.name() + " is required but value is null");
      }
      return;
    }

    // For non-null values, validate against the type
    Class<?> javaType = column.javaType();
    if (!javaType.isInstance(value)) {
      throw new IllegalArgumentException(
          "Value for column " + column.name() + " must be of type " + javaType.getSimpleName()
              + " but was " + value.getClass().getSimpleName());
    }
  }

  /**
   * @deprecated Use {@link #with(String, Object)} instead.
   */
  @Deprecated
  public void set(String column, Object value) {
    throw new UnsupportedOperationException("DataRow is immutable. Use 'with' methods instead.");
  }

  /**
   * @deprecated Use {@link #with(int, Object)} instead.
   */
  @Deprecated
  public void set(int index, Object value) {
    throw new UnsupportedOperationException("DataRow is immutable. Use 'with' methods instead.");
  }
}