Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ClassCastException from Get Table Cell Value when application renders Boolean to text #59

Closed
mvuorenmaa opened this issue Oct 30, 2014 · 3 comments

Comments

@mvuorenmaa
Copy link

Background

After we switched to remoteswinglibrary-1.1.1 from a fairly old swinglibrary-1.1.3, we faced a new problem with Get Table Cell Value keyword. Our application is extracting table cell values from a fairly large tree table and the implementation is originally done with quite early version of Swing. This added some complexity to the issue.

Problem

One piece of text we saw in the Get Table Cell Value keyword definition was leading us into right direction:

"Starting from SwingLibrary 1.1.4, value from cell rendered with check box is string true/false."

With remoteswinglibrary-1.1.1 getting cell values from the tree table always led to an exception like this:

16:10:28.392 DEBUG XyzCellRenderer cannot be cast to javax.swing.AbstractButton
                             at org.robotframework.swing.table.CellValueExtractor.textOf(CellValueExtractor.java:26)
                             at org.robotframework.swing.table.TableOperator.getCellValue(TableOperator.java:58)
                             at org.robotframework.swing.keyword.table.TableKeywords.getTableCellValue(TableKeywords.java:122)

The problem actually wasn’t the our TreeTable component as we first thought. We noticed that swinglibrary was assuming that Boolean values are rendered as buttons, while our implementation is intentionally rendering Booleans in text format. Combined with our tree table cell renderer implementations, the swinglibrary was treating all types of table cells as AbstractButton based.

Fix

Original CellValueExtractor code:

public String textOf(int row, int col) {
    try {
        Component cellRendererComponent = getCellRendererComponent(row, col);
        if (isCheckboxRenderer(cellRendererComponent))
            return new Boolean(((AbstractButton) cellRendererComponent).isSelected()).toString();
        return coerceToWithText(cellRendererComponent).getText();
    } catch (AllMethodsNotImplementedException e) {
        return wrapElementToWithText(row, col).getText();
    }
}

. . .

private boolean isCheckboxRenderer(Component cellRendererComponent) {
    TableCellRenderer defaultCheckboxRenderer = ((JTable) jTableOperator.getSource()).getDefaultRenderer(Boolean.class);
    return (defaultCheckboxRenderer.getClass().isInstance(cellRendererComponent));
}

In our implementation the renderer component for Booleans is in the same class hierarchy with other renderer classes. When the isCheckboxRenderer() does the isInstance() call, the result is always true. In textOf() the code makes an additional assumption that the renderer is an instance of AbstractButton. This is actually not checked in the isCheckboxRenderer() method.

Changed CellValueExtractor code:

private boolean isButtonBasedRenderer(Component cellRendererComponent) {
    TableCellRenderer defaultCheckboxRenderer = ((JTable) jTableOperator.getSource()).getDefaultRenderer(Boolean.class);
    return (defaultCheckboxRenderer.getClass().isInstance(cellRendererComponent) &&
            cellRendererComponent instanceof AbstractButton);
}

We modified isCheckboxRenderer() method and renamed it to be a bit more descriptive. The purpose there is to make sure the renderer actually is based on AbstractButton by adding the '&& cellRendererComponent instanceof AbstractButton' part. This will make sure the renderer is AbstractButton based before casting it in textOf() method.

This has worked for us and not broken anything so far. The fix is quite minimal to avoid possible ill-effects, trying just to avoid the situation when the renderer was wrongly cast into AbstractButton. More exotic Button based renderer implementations could still cause some kind of problems.

@pekkaklarck
Copy link
Member

Does this problem occur also with plain SwingLibrary or only with RemoteSwingLibrary? At least in the latter case it would be a good idea to submit an issue to RemoteSwingLibrary tracker too. The fix apparently belongs to SwingLibrary, so we can keep this issue open and the new issue can refer to this one.

Since you already have a fix ready, it would be great if you could also provide a pull request. It would make reviewing the changes easier for us.

@mvuorenmaa
Copy link
Author

We believe the issue occurs with both RemoteSwingLibrary and SwingLibrary, but have tested it only on top of RemoteSwingLibrary. An issue referring to this one has been created to RemoteSwingLibrary.

We will try to proceed with the pull request soon.

mvuorenmaa pushed a commit to mvuorenmaa/SwingLibrary that referenced this issue Nov 10, 2014
jussimalinen added a commit that referenced this issue Feb 9, 2015
@jussimalinen
Copy link
Member

Okay, I want to get the new version of RemoteSwingLibrary out and as this doesn't break any tests, I will just release it with this functionality without a new test..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants