001package io.prometheus.metrics.model.snapshots;
002
003import java.util.ArrayList;
004import java.util.Arrays;
005import java.util.Collections;
006import java.util.Comparator;
007import java.util.Iterator;
008import java.util.List;
009
010/** Immutable list of quantiles. */
011public class Quantiles implements Iterable<Quantile> {
012
013  private final List<Quantile> quantiles;
014  public static final Quantiles EMPTY = new Quantiles(Collections.emptyList());
015
016  private Quantiles(List<Quantile> quantiles) {
017    quantiles = new ArrayList<>(quantiles);
018    quantiles.sort(Comparator.comparing(Quantile::getQuantile));
019    this.quantiles = Collections.unmodifiableList(quantiles);
020    validate();
021  }
022
023  private void validate() {
024    for (int i = 0; i < quantiles.size() - 1; i++) {
025      if (quantiles.get(i).getQuantile() == quantiles.get(i + 1).getQuantile()) {
026        throw new IllegalArgumentException(
027            "Duplicate " + quantiles.get(i).getQuantile() + " quantile.");
028      }
029    }
030  }
031
032  /**
033   * Create a new Quantiles instance. You can either create Quantiles with one of the static {@code
034   * Quantiles.of(...)} methods, or you can use the {@link Quantiles#builder()}.
035   */
036  public static Quantiles of(List<Quantile> quantiles) {
037    return new Quantiles(quantiles);
038  }
039
040  /**
041   * Create a new Quantiles instance. You can either create Quantiles with one of the static {@code
042   * Quantiles.of(...)} methods, or you can use the {@link Quantiles#builder()}.
043   */
044  public static Quantiles of(Quantile... quantiles) {
045    return of(Arrays.asList(quantiles));
046  }
047
048  public int size() {
049    return quantiles.size();
050  }
051
052  public Quantile get(int i) {
053    return quantiles.get(i);
054  }
055
056  @Override
057  public Iterator<Quantile> iterator() {
058    return quantiles.iterator();
059  }
060
061  public static Builder builder() {
062    return new Builder();
063  }
064
065  public static class Builder {
066
067    private final List<Quantile> quantiles = new ArrayList<>();
068
069    private Builder() {}
070
071    /** Add a quantile. Call multiple times to add multiple quantiles. */
072    public Builder quantile(Quantile quantile) {
073      quantiles.add(quantile);
074      return this;
075    }
076
077    /**
078     * Add a quantile. Call multiple times to add multiple quantiles.
079     *
080     * @param quantile 0.0 &lt;= quantile &lt;= 1.0
081     * @param value the quantile value
082     */
083    public Builder quantile(double quantile, double value) {
084      quantiles.add(new Quantile(quantile, value));
085      return this;
086    }
087
088    public Quantiles build() {
089      return new Quantiles(quantiles);
090    }
091  }
092}