gt:     else if (att.type() == Attribute.DATE)
context: /*
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
   *   the Free Software Foundation, either version 3 of the License, or
   *   (at your option) any later version.
   *
   *   This program is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *   GNU General Public License for more details.
   *
   *   You should have received a copy of the GNU General Public License
   *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  /**
   * InstancesView.java
   * Copyright (C) 2016 University of Waikato, Hamilton, NZ
   */
  
  package adams.ml.data;
  
  import adams.core.DateFormat;
  import adams.core.DateUtils;
  import adams.core.Utils;
  import adams.core.exception.NotImplementedException;
  import adams.core.management.LocaleHelper;
  import adams.data.SharedStringsTable;
  import adams.data.spreadsheet.Cell;
  import adams.data.spreadsheet.Cell.ContentType;
  import adams.data.spreadsheet.DataRow;
  import adams.data.spreadsheet.HeaderRow;
  import adams.data.spreadsheet.Row;
  import adams.data.spreadsheet.RowComparator;
  import adams.data.spreadsheet.SpreadSheet;
  import adams.data.spreadsheet.SpreadSheetUtils;
  import adams.data.spreadsheet.SpreadSheetView;
  import weka.core.Attribute;
  import weka.core.DenseInstance;
  import weka.core.Instances;
  import weka.filters.Filter;
  import weka.filters.unsupervised.attribute.Remove;
  
  import java.text.NumberFormat;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Locale;
  import java.util.TimeZone;
  
  /**
   * Provides a view of an {@link Instances} object.
   *
   * @author FracPete (fracpete at waikato dot ac dot nz)
   * @version $Revision$
   */
  public class InstancesView
    implements Dataset {
  
    private static final long serialVersionUID = -6570030309091506840L;
  
    /** the underlying data. */
    protected Instances m_Data;
  
    /** the header row. */
    protected InstancesHeaderRow m_Header;
  
    /** the shared string table. */
    protected SharedStringsTable m_SharedStringsTable;
  
    /**
     * Initializes the view with a dummy dataset.
     */
    public InstancesView() {
      this(createDummy());
    }
  
    /**
     * Returns a dummy dataset.
     *
     * @return		the dataset
     */
    protected static Instances createDummy() {
      ArrayList<Attribute>	atts;
  
      atts = new ArrayList<>();
      atts.add(new Attribute("dummy"));
  
      return new Instances("dummy", atts, 0);
    }
  
    /**
     * Initializes the view.
     *
     * @param data	the data to use
     */
    public InstancesView(Instances data) {
      m_Data               = data;
      m_SharedStringsTable = new SharedStringsTable();
      m_Header             = new InstancesHeaderRow(this);
    }
  
    /**
     * Returns the underlying Instances.
     *
     * @return		the underlying data
     */
    public Instances getData() {
      return m_Data;
    }
  
    /**
     * Turns the rowKey into a row index.
     *
     * @param rowKey	the rowKey to convert
     * @return		the row index, -1 if failed to convert
     */
    protected int rowKeyToIndex(String rowKey) {
      if (Utils.isInteger(rowKey))
        return Integer.parseInt(rowKey);
      else
        return -1;
    }
  
    /**
     * Turns the cellKey into a column index.
     *
     * @param cellKey	the cellKey to convert
     * @return		the column index, -1 if failed to convert
     */
    protected int cellKeyToIndex(String cellKey) {
      if (Utils.isInteger(cellKey))
        return Integer.parseInt(cellKey);
      else
        return -1;
    }
  
    /**
     * Ignored.
     *
     * @param comment	the comment to add
     */
    @Override
    public void addComment(List<String> comment) {
    }
  
    /**
     * Returns the comments.
     *
     * @return		always empty
     */
    @Override
    public List<String> getComments() {
      return new ArrayList<>();
    }
  
    /**
     * Removes all cells, but leaves comments.
     */
    @Override
    public void clear() {
      m_Data.clear();
    }
  
    /**
     * Returns the header row.
     *
     * @return		the row
     */
    @Override
    public HeaderRow getHeaderRow() {
      return m_Header;
    }
  
    /**
     * Returns the name of the specified column.
     *
     * @param colIndex	the index of the column
     * @return		the name of the column
     */
    @Override
    public String getColumnName(int colIndex) {
      return m_Data.attribute(colIndex).name();
    }
  
    /**
     * Returns a list of the names of all columns (i.e., the content the header
     * row cells).
     *
     * @return		the names of the columns
     */
    @Override
    public List<String> getColumnNames() {
      List<String>	result;
      int			i;
  
      result = new ArrayList<>();
      for (i = 0; i < m_Data.numAttributes(); i++)
        result.add(m_Data.attribute(i).name());
  
      return result;
    }
  
    /**
     * Returns whether the spreadsheet already contains the row with the given index.
     *
     * @param rowIndex	the index to look for
     * @return		true if the row already exists
     */
    @Override
    public boolean hasRow(int rowIndex) {
      return (rowIndex < m_Data.numInstances());
    }
  
    /**
     * Returns whether the spreadsheet already contains the row with the given key.
     *
     * @param rowKey	the key to look for
     * @return		true if the row already exists
     */
    @Override
    public boolean hasRow(String rowKey) {
      int		row;
  
      row = rowKeyToIndex(rowKey);
      return (row >= 0) || (row < m_Data.numInstances());
    }
  
    /**
     * Creates a new cell.
     *
     * @return		the new instance, null in case of an instantiation error
     */
    @Override
    public Cell newCell() {
      return null;
    }
  
    /**
     * Appends a row to the spreadsheet.
     *
     * @return		the created row
     */
    @Override
    public DataRow addRow() {
      DenseInstance	inst;
  
      inst = new DenseInstance(getColumnCount());
      inst.setDataset(m_Data);
      m_Data.add(inst);
  
      return new InstanceView(this, inst);
    }
  
    /**
     * Adds a row with the given key to the list and returns the created object.
     * If the row already exists, then this row is returned instead and no new
     * object created.
     *
     * @param rowKey	the key for the row to create
     * @return		the created row or the already existing row
     */
    @Override
    public DataRow addRow(String rowKey) {
      throw new NotImplementedException();
    }
  
    /**
     * Inserts a row at the specified location.
     *
     * @param index	the index where to insert the row
     * @return		the created row
     */
    @Override
    public DataRow insertRow(int index) {
      DenseInstance	inst;
  
      inst = new DenseInstance(getColumnCount());
      inst.setDataset(m_Data);
      m_Data.add(index, inst);
  
      return new InstanceView(this, inst);
    }
  
    /**
     * Removes the specified row.
     *
     * @param rowIndex	the row to remove
     * @return		the row that was removed, null if none removed
     */
    @Override
    public Row removeRow(int rowIndex) {
      if ((rowIndex >= 0) && (rowIndex < getRowCount()))
        return new InstanceView(this, m_Data.remove(rowIndex));
      else
        return null;
    }
  
    /**
     * Removes the specified row.
     *
     * @param rowKey	the row to remove
     * @return		the row that was removed, null if none removed
     */
    @Override
    public Row removeRow(String rowKey) {
      return removeRow(rowKeyToIndex(rowKey));
    }
  
    /**
     * Inserts a column at the specified location.
     * <br><br>
     * Not implemented!
     *
     * @param columnIndex	the position of the column
     * @param header	the name of the column
     */
    @Override
    public void insertColumn(int columnIndex, String header) {
      throw new NotImplementedException();
  
    }
  
    /**
     * Inserts a column at the specified location.
     * <br><br>
     * Not implemented!
     *
     * @param columnIndex	the position of the column
     * @param header	the name of the column
     * @param initial	the initial value for the cells, "null" for missing
     * 			values (in that case no cells are added)
     */
    @Override
    public void insertColumn(int columnIndex, String header, String initial) {
      throw new NotImplementedException();
    }
  
    /**
     * Inserts a column at the specified location.
     * <br><br>
     * Not implemented!
     *
     * @param columnIndex	the position of the column
     * @param header	the name of the column
     * @param initial	the initial value for the cells, "null" for missing
     * 			values (in that case no cells are added)
     * @param forceString	whether to enforce the value to be set as string
     */
    @Override
    public void insertColumn(int columnIndex, String header, String initial, boolean forceString) {
      throw new NotImplementedException();
    }
  
    /**
     * Removes the specified column.
     * <br><br>
     * Not implemented!
     *
     * @param columnIndex	the column to remove
     * @return		true if removed
     */
    @Override
    public boolean removeColumn(int columnIndex) {
      throw new NotImplementedException();
    }
  
    /**
     * Removes the specified column.
     * <br><br>
     * Not implemented!
     *
     * @param columnKey	the column to remove
     * @return		true if removed
     */
    @Override
    public boolean removeColumn(String columnKey) {
      throw new NotImplementedException();
    }
  
    /**
     * Returns the row associated with the given row key, null if not found.
     *
     * @param rowKey	the key of the row to retrieve
     * @return		the row or null if not found
     */
    @Override
    public DataRow getRow(String rowKey) {
      return getRow(rowKeyToIndex(rowKey));
    }
  
    /**
     * Returns the row at the specified index.
     *
     * @param rowIndex	the 0-based index of the row to retrieve
     * @return		the row
     */
    @Override
    public DataRow getRow(int rowIndex) {
      if ((rowIndex >= 0) && (rowIndex < getRowCount()))
        return new InstanceView(this, m_Data.instance(rowIndex));
      else
        return null;
    }
  
    /**
     * Returns the row key at the specified index.
     *
     * @param rowIndex	the 0-based index of the row key to retrieve
     * @return		the row key
     */
    @Override
    public String getRowKey(int rowIndex) {
      return "" + rowIndex;
    }
  
    /**
     * Returns the row index of the specified row.
     *
     * @param rowKey	the row identifier
     * @return		the 0-based row index, -1 if not found
     */
    @Override
    public int getRowIndex(String rowKey) {
      return rowKeyToIndex(rowKey);
    }
  
    /**
     * Returns the cell index of the specified cell (in the header row).
     *
     * @param cellKey	the cell identifier
     * @return		the 0-based column index, -1 if not found
     */
    @Override
    public int getCellIndex(String cellKey) {
      return cellKeyToIndex(cellKey);
    }
  
    /**
     * Checks whether the cell with the given indices already exists.
     *
     * @param rowIndex	the index of the row to look for
     * @param columnIndex	the index of the cell in the row to look for
     * @return		true if the cell exists
     */
    @Override
    public boolean hasCell(int rowIndex, int columnIndex) {
      return (rowIndex >= 0) && (rowIndex < getRowCount())
        && (columnIndex >= 0) && (columnIndex < getColumnCount());
    }
  
    /**
     * Returns the corresponding cell or null if not found.
     *
     * @param rowIndex	the index of the row the cell is in
     * @param columnIndex	the column of the cell to retrieve
     * @return		the cell or null if not found
     */
    @Override
    public Cell getCell(int rowIndex, int columnIndex) {
      Row		row;
  
      row = getRow(rowIndex);
      if (row != null)
        return row.getCell(columnIndex);
      else
        return null;
    }
  
    /**
     * Returns the position of the cell or null if not found. A position is a
     * combination of a number of letters (for the column) and number (for the
     * row).
     *
     * @param rowKey	the key of the row the cell is in
     * @param cellKey	the key of the cell to retrieve
     * @return		the position string or null if not found
     */
    @Override
    public String getCellPosition(String rowKey, String cellKey) {
      return SpreadSheetUtils.getCellPosition(rowKeyToIndex(rowKey), cellKeyToIndex(cellKey));
    }
  
    /**
     * Returns a collection of all row keys.
     *
     * @return		the row keys
     */
    @Override
    public Collection<String> rowKeys() {
      List<String>	result;
      int			i;
  
      result = new ArrayList<>();
      for (i = 0; i < getRowCount(); i++)
        result.add("" + i);
  
      return result;
    }
  
    /**
     * Returns all rows.
     *
     * @return		the rows
     */
    @Override
    public Collection<DataRow> rows() {
      List<DataRow>	result;
      int			i;
  
      result = new ArrayList<>();
      for (i = 0; i < getRowCount(); i++)
        result.add(getRow(i));
  
      return result;
    }
  
    /**
     * Sorts the rows according to the row keys.
     * <br>
     * Does nothing.
     *
     * @see	#rowKeys()
     */
    @Override
    public void sortRowKeys() {
    }
  
    /**
     * Sorts the rows according to the row keys.
     * <br>
     * Does nothing.
     *
     * @param comp	the comparator to use
     * @see		#rowKeys()
     */
    @Override
    public void sortRowKeys(Comparator<String> comp) {
    }
  
    /**
     * Sorts the rows based on the values in the specified column.
     * <br><br>
     * NB: the row keys will change!
     *
     * @param index	the index (0-based) of the column to sort on
     * @param asc		wether sorting is ascending or descending
     * @see 		#sort(RowComparator)
     */
    @Override
    public void sort(int index, boolean asc) {
      m_Data.sort(index);
      if (!asc)
        Collections.reverse(m_Data);
    }
  
    /**
     * Sorts the rows using the given comparator.
     * <br><br>
     * Not implemented.
     *
     * @param comp	the row comparator to use
     */
    @Override
    public void sort(RowComparator comp) {
  
    }
  
    /**
     * Sorts the rows using the given comparator.
     * <br><br>
     * Not implemented.
     *
     * @param comp	the row comparator to use
     * @param unique	whether to drop any duplicate rows (based on row comparator)
     */
    @Override
    public void sort(RowComparator comp, boolean unique) {
  
    }
  
    /**
     * Returns the number of columns.
     *
     * @return		the number of columns
     */
    @Override
    public int getColumnCount() {
      return m_Data.numAttributes();
    }
  
    /**
     * Returns the number of rows currently stored.
     *
     * @return		the number of rows
     */
    @Override
    public int getRowCount() {
      return m_Data.numInstances();
    }
  
    /**
     * Checks whether the given column is numeric or not. Does not accept
     * missing values.
     *
     * @param columnIndex	the index of the column to check
     * @return		true if purely numeric
     * @see		#getContentTypes(int)
     */
    @Override
    public boolean isNumeric(int columnIndex) {
      return isNumeric(columnIndex, false);
    }
  
    /**
     * Checks whether the given column is numeric or not. Can accept missing
     * values.
     *
     * @param columnIndex	the index of the column to check
     * @return		true if purely numeric
     * @see		#getContentTypes(int)
     */
    @Override
    public boolean isNumeric(int columnIndex, boolean allowMissing) {
      boolean	result;
      int		i;
  
      result = (m_Data.attribute(columnIndex).type() == Attribute.NUMERIC);
      if (result && !allowMissing) {
        for (i = 0; i < m_Data.numInstances(); i++) {
  	if (m_Data.instance(i).isMissing(columnIndex)) {
  	  result = false;
  	  break;
  	}
        }
      }
  
      return result;
    }
  
    /**
     * Checks whether the given column is of the specific content type or not.
     *
     * @param columnIndex	the index of the column to check
     * @param type	the content type to check
     * @return		true if column purely consists of this content type
     * @see		#getContentType(int)
     */
    @Override
    public boolean isContentType(int columnIndex, ContentType type) {
      Attribute	att;
  
      att = m_Data.attribute(columnIndex);
      if ((type == ContentType.DOUBLE) && (att.type() == Attribute.NUMERIC))
        return true;
      else if ((type == ContentType.DATETIMEMSEC) && (att.type() == Attribute.DATE))
        return true;
      else if ((type == ContentType.STRING) && (att.type() == Attribute.NOMINAL))
        return true;
      else if ((type == ContentType.STRING) && (att.type() == Attribute.STRING))
        return true;
  
      return false;
    }
  
    /**
     * Returns the pure content type of the given column, if available.
     *
     * @param columnIndex	the index of the column to check
     * @return		the content type that this column consists of solely, null if mixed
     */
    @Override
    public ContentType getContentType(int columnIndex) {
      Collection<ContentType>	types;
  
      types = getContentTypes(columnIndex);
      if (types.size() == 1)
        return types.iterator().next();
      else
        return null;
    }
  
    /**
     * Returns the all content types of the given column, if available.
     *
     * @param columnIndex	the index of the column to check
     * @return		the content types that this column consists of
     */
    @Override
    public Collection<ContentType> getContentTypes(int columnIndex) {
      List<ContentType>	result;
      Attribute		att;
      int			i;
  
      result = new ArrayList<>();
      att    = m_Data.attribute(columnIndex);
      if (att.type() == Attribute.NUMERIC)
        result.add(ContentType.DOUBLE);
  