f7
f7 is a spreadsheet formula execution library
git clone https://git.vogt.world/f7.git
Log | Files | README.md | LICENSE.md
← All files
name: src/main/java/io/protobase/f7/models/CellQuery.java
-rw-r--r--
5383
  1package io.protobase.f7.models;
  2
  3import com.google.common.base.MoreObjects;
  4import com.google.common.collect.Range;
  5import io.protobase.f7.errors.ValueException;
  6import io.protobase.f7.utils.AlphaUtils;
  7
  8import java.util.Objects;
  9import java.util.Optional;
 10
 11/**
 12 * A range query represents a query of one or more cells over a single grid. It is composed of two dimensional ranges:
 13 * rows and columns, both of which can be unbounded at the lower, or upper ends of the range.
 14 */
 15public class CellQuery extends BaseObject {
 16  /**
 17   * Name of the grid being queried.
 18   */
 19  private String grid;
 20  /**
 21   * Range of columns.
 22   */
 23  private Range<Integer> columns;
 24  /**
 25   * Range of rows.
 26   */
 27  private Range<Integer> rows;
 28
 29  public CellQuery(String grid, Range<Integer> columns, Range<Integer> rows) {
 30    this.grid = grid;
 31    this.columns = columns;
 32    this.rows = rows;
 33  }
 34
 35  public static Builder builder() {
 36    return new Builder();
 37  }
 38
 39  public static Builder builder(CellQuery query) {
 40    return new Builder(query);
 41  }
 42
 43  public Optional<String> getGrid() {
 44    return Optional.ofNullable(grid);
 45  }
 46
 47  public Integer getStartColumn() {
 48    return columns.lowerEndpoint();
 49  }
 50
 51  public Integer getEndColumn() {
 52    return columns.upperEndpoint();
 53  }
 54
 55  public Integer getStartRow() {
 56    return rows.lowerEndpoint();
 57  }
 58
 59  public Integer getEndRow() {
 60    return rows.upperEndpoint();
 61  }
 62
 63  /**
 64   * Does this query intersect with the other one?
 65   *
 66   * @param other - other query.
 67   * @return true if at least one cell overlaps.
 68   */
 69  public boolean intersects(CellQuery other) {
 70    return other.columns.isConnected(this.columns) && other.rows.isConnected(this.rows);
 71  }
 72
 73  /**
 74   * Bound this query using an upper column and upper row. Will default to the lower of the upper column passed in,
 75   * and the upper column bound existing on the columns range. Same for rows.
 76   *
 77   * @param upperColumn - upper endpoint for columns to default to.
 78   * @param upperRow    - upper endpoint of rows to default to.
 79   * @return bounded query.
 80   */
 81  public CellQuery toBounded(int upperColumn, int upperRow) {
 82    if (!Range.closed(0, upperColumn).isConnected(columns) && !Range.closed(0, upperRow).isConnected(rows)) {
 83      return this;
 84    }
 85    return CellQuery.builder(this)
 86        .columnsBetween(this.columns.lowerEndpoint(),
 87            Math.min(upperColumn, columns.hasUpperBound() ? columns.upperEndpoint() : upperColumn))
 88        .rowsBetween(this.rows.lowerEndpoint(),
 89            Math.min(upperRow, rows.hasUpperBound() ? rows.upperEndpoint() : upperRow))
 90        .build();
 91  }
 92
 93  @Override
 94  public Object[] significantAttributes() {
 95    return new Object[]{
 96        grid,
 97        columns,
 98        rows
 99    };
100  }
101
102  @Override
103  public String toString() {
104    return MoreObjects.toStringHelper(this)
105        .add("grid", grid)
106        .add("columns", columns)
107        .add("rows", rows)
108        .toString();
109  }
110
111  public static class Builder {
112    private String gridName;
113    private Range<Integer> columns;
114    private Range<Integer> rows;
115
116    public Builder() {
117    }
118
119    public Builder(CellQuery query) {
120      this.gridName = query.grid;
121      this.columns = query.columns;
122      this.rows = query.rows;
123    }
124
125    public Builder grid(String gridName) {
126      this.gridName = gridName;
127      return this;
128    }
129
130    public Builder columnsBetween(String low, String high) {
131      columns = Range.closed(AlphaUtils.columnToInt(low), AlphaUtils.columnToInt(high));
132      return this;
133    }
134
135    public Builder columnsBetween(int low, int high) {
136      columns = Range.closed(low, high);
137      return this;
138    }
139
140    public Builder rowsBetween(String low, String high) {
141      rows = Range.closed(Integer.parseInt(low) - 1, Integer.parseInt(high) - 1);
142      return this;
143    }
144
145    public Builder rowsBetween(int low, int high) {
146      rows = Range.closed(low, high);
147      return this;
148    }
149
150    public Builder openColumnsStartingAt(String startColumn) {
151      columns = Range.atLeast(AlphaUtils.columnToInt(startColumn));
152      return this;
153    }
154
155    public Builder openColumnsStartingAt(int startColumn) {
156      columns = Range.atLeast(startColumn);
157      return this;
158    }
159
160    public Builder openColumnsStartingAtZero() {
161      columns = Range.atLeast(0);
162      return this;
163    }
164
165    public Builder openRowsStartingAt(String startRow) {
166      rows = Range.atLeast(Integer.parseInt(startRow) - 1);
167      return this;
168    }
169
170    public Builder openRowsStartingAt(int startRow) {
171      rows = Range.atLeast(startRow);
172      return this;
173    }
174
175    public Builder openRowsStartingAtZero() {
176      rows = Range.atLeast(0);
177      return this;
178    }
179
180    public Builder expand(CellQuery query) {
181      if (Objects.isNull(columns)) {
182        columns = query.columns;
183      } else {
184        columns = columns.span(query.columns);
185      }
186      if (Objects.isNull(rows)) {
187        rows = query.rows;
188      } else {
189        rows = rows.span(query.rows);
190      }
191      if (Objects.nonNull(gridName) && !gridName.equals(query.getGrid().get())) {
192        throw new ValueException("Different grid names.");
193      } else {
194        gridName = query.getGrid().get();
195      }
196      return this;
197    }
198
199    public CellQuery build() {
200      return new CellQuery(gridName, Objects.requireNonNull(columns), Objects.requireNonNull(rows));
201    }
202  }
203}