package tech.tablesaw.columns.strings;

import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;
import tech.tablesaw.api.CategoricalColumn;
import tech.tablesaw.api.ColumnType;
import tech.tablesaw.columns.AbstractColumn;
import tech.tablesaw.columns.AbstractColumnParser;
import tech.tablesaw.columns.Column;

/** Abstract super class for Text like columns. */
public abstract class AbstractStringColumn<C extends AbstractColumn<C, String>>
    extends AbstractColumn<C, String>
    implements CategoricalColumn<String>, StringFilters, StringMapFunctions, StringReduceUtils {
  private StringColumnFormatter printFormatter = new StringColumnFormatter();

  public AbstractStringColumn(ColumnType type, String name, AbstractColumnParser<String> parser) {
    super(type, name, parser);
  }

  public void setPrintFormatter(StringColumnFormatter formatter) {
    Preconditions.checkNotNull(formatter);
    this.printFormatter = formatter;
  }

  public StringColumnFormatter getPrintFormatter() {
    return printFormatter;
  }

  @Override
  public String getString(int row) {
    return printFormatter.format(get(row));
  }

  @Override
  public String getUnformattedString(int row) {
    return String.valueOf(get(row));
  }

  /**
   * Returns the largest ("top") n values in the column
   *
   * @param n The maximum number of records to return. The actual number will be smaller if n is
   *     greater than the number of observations in the column
   * @return A list, possibly empty, of the largest observations
   */
  public List<String> top(int n) {
    List<String> top = new ArrayList<>();
    Column<String> copy = this.copy();
    copy.sortDescending();
    for (int i = 0; i < n; i++) {
      top.add(copy.get(i));
    }
    return top;
  }

  /**
   * Returns the smallest ("bottom") n values in the column
   *
   * @param n The maximum number of records to return. The actual number will be smaller if n is
   *     greater than the number of observations in the column
   * @return A list, possibly empty, of the smallest n observations
   */
  public List<String> bottom(int n) {
    List<String> bottom = new ArrayList<>();
    Column<String> copy = this.copy();
    copy.sortAscending();
    for (int i = 0; i < n; i++) {
      bottom.add(copy.get(i));
    }
    return bottom;
  }

  @Override
  public Column<String> append(Column<String> column, int row) {
    return append(column.getUnformattedString(row));
  }

  @Override
  public Column<String> set(int row, Column<String> column, int sourceRow) {
    return set(row, column.getUnformattedString(sourceRow));
  }

  @Override
  public int byteSize() {
    return type().byteSize();
  }

  @Override
  public int compare(String o1, String o2) {
    return o1.compareTo(o2);
  }
}

@@ -610,16 +610,17 @@
 Utils %7B%0A
+%0A
   privat
@@ -690,16 +690,87 @@
 ter();%0A%0A
+  /** Constructs a column of the given ColumnType, name, and parser */%0A
   public
@@ -892,24 +892,265 @@
 rser);%0A  %7D%0A%0A
+  /**%0A   * Sets an %7B@link StringColumnFormatter%7D which will be used to format the display of data from%0A   * this column when it is printed (using, for example, Table:print()) and optionally when written%0A   * to a text file like a CSV.%0A   */%0A
   public voi
@@ -1289,16 +1289,76 @@
 r;%0A  %7D%0A%0A
+  /** Returns the current %7B@link StringColumnFormatter%7D. */%0A
   public
@@ -1430,24 +1430,47 @@
 atter;%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Override%0A
@@ -1547,32 +1547,55 @@
 get(row));%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Override%0A  pu
@@ -2754,24 +2754,47 @@
 ottom;%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Override%0A
@@ -2908,32 +2908,55 @@
 ing(row));%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Override%0A  pu
@@ -3086,32 +3086,55 @@
 urceRow));%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Override%0A  pu
@@ -3190,16 +3190,39 @@
 );%0A  %7D%0A%0A
+  /** %7B@inheritDoc%7D */%0A
   @Overr

Add Javadoc for AbstractStringColumn