001    /*
002     * Created on Oct 13, 2007
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005     * in compliance with the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License
010     * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011     * or implied. See the License for the specific language governing permissions and limitations under
012     * the License.
013     *
014     * Copyright @2008-2010 the original author or authors.
015     */
016    package org.fest.swing.data;
017    
018    import static java.lang.String.valueOf;
019    import static org.fest.swing.edt.GuiActionRunner.execute;
020    import static org.fest.swing.exception.ActionFailedException.actionFailure;
021    import static org.fest.swing.query.JTableColumnByIdentifierQuery.columnIndexByIdentifier;
022    import static org.fest.util.Strings.concat;
023    import static org.fest.util.Strings.quote;
024    
025    import javax.swing.JTable;
026    
027    import org.fest.swing.annotation.RunsInEDT;
028    import org.fest.swing.cell.JTableCellReader;
029    import org.fest.swing.edt.GuiQuery;
030    import org.fest.swing.exception.ActionFailedException;
031    
032    /**
033     * Understands lookup of a cell in a <code>{@link JTable}</code> by column identifier.
034     * <p>
035     * Example:
036     * <pre>
037     * // import static org.fest.swing.data.TableCellByColumnId.row;
038     * <code>{@link TableCell}</code> cell = dialog.table("records").cell({@link TableCellByColumnId#row(int) row}(3).columnId("firstColumn"));
039     * </pre>
040     * </p>
041     *
042     * @author Alex Ruiz
043     */
044    public class TableCellByColumnId implements TableCellFinder {
045    
046      public final int row;
047      public final Object columnId;
048    
049      /**
050       * Starting point for the creation of a <code>{@link TableCellByColumnId}</code>.
051       * <p>
052       * Example:
053       * <pre>
054       * // import static org.fest.swing.data.TableCellByColumnId.row;
055       * TableCellByColumnId cell = row(5).columnId("hobbyColumn");
056       * </pre>
057       * </p>
058       * @param row the row index of the table cell to find.
059       * @return the created builder.
060       */
061      public static TableCellBuilder row(int row) { return new TableCellBuilder(row); }
062    
063      /**
064       * Understands creation of <code>{@link TableCellByColumnId}</code>s.
065       *
066       * @author Alex Ruiz
067       */
068      public static class TableCellBuilder {
069        private final int row;
070    
071        TableCellBuilder(int row) { this.row = row; }
072    
073        /**
074         * Creates a new table cell finder using the row index specified in
075         * <code>{@link TableCellByColumnId#row(int)}</code> and the column id specified as the argument in this method.
076         * @param columnId the name of the column in the table cell to find.
077         * @return the created finder.
078         */
079        public TableCellByColumnId columnId(Object columnId) {
080          return new TableCellByColumnId(row, columnId);
081        }
082      }
083    
084      protected TableCellByColumnId(int row, Object columnId) {
085        this.row = row;
086        this.columnId = columnId;
087      }
088    
089      /**
090       * Finds a cell in the given <code>{@link JTable}</code> that has a matching row index and column id.
091       * @param table the target <code>JTable</code>.
092       * @param cellReader knows how to read the contents of a cell in a <code>JTable</code>.
093       * @return the cell found, if any.
094       * @throws ActionFailedException if a matching cell could not be found.
095       */
096      @RunsInEDT
097      public TableCell findCell(JTable table, JTableCellReader cellReader) {
098        return findCell(table, row, columnId);
099      }
100    
101      @RunsInEDT
102      private static TableCell findCell(final JTable table, final int row, final Object columnId) {
103        return execute(new GuiQuery<TableCell>() {
104          protected TableCell executeInEDT() {
105            int column = columnIndexByIdentifier(table, columnId);
106            if (column == -1) failColumnIndexNotFound(columnId);
107            table.convertColumnIndexToView(table.getColumn(columnId).getModelIndex());
108            return new TableCell(row, column);
109          }
110        });
111      }
112    
113      private static ActionFailedException failColumnIndexNotFound(Object columnId) {
114        throw actionFailure(concat("Unable to find a column with id ", quote(columnId)));
115      }
116    
117      @Override public String toString() {
118        return concat(getClass().getName(), "[row=", valueOf(row), ", columnId=", quote(columnId), "]");
119      }
120    }