package com.redheap.selenium.component;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.Keys;
import org.openqa.selenium.Platform;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
public class AdfTable extends AdfComponent {
private static final String SUBID_disclosureID = "disclosureID"; // [99]disclosureId returns <a> element
private static final String JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWKEY =
JS_FIND_COMPONENT +
"var child=comp.findComponent(arguments[1],arguments[2]); return child?child.getClientId():null";
private static final String JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWINDEX =
JS_FIND_PEER +
"var idx=peer.getRowKey(arguments[2]); if (!idx){return null}var child=comp.findComponent(arguments[1],idx); return child?child.getClientId():null";
private static final String JS_IS_ROW_DISCLOSED =
JS_FIND_COMPONENT + "return comp.isDisclosed(arguments[1])===true";
private static final String JS_SCROLLTO_ROWINDEX = JS_FIND_COMPONENT + "comp.scrollToRowIndex(arguments[1])";
private static final String JS_GET_FOCUSED_ROWKEY = JS_FIND_PEER + "return peer.GetFocusedRowKey()";
private static final String JS_GET_ROWKEY = JS_FIND_PEER + "return peer.getRowKey(arguments[1])";
private static final String JS_GET_ROWINDEX = JS_FIND_PEER + "return peer.getRowIndex(arguments[1])";
private static final String JS_SELECTED_ROWS =
JS_FIND_PEER +
"var keys=Object.keys(comp.getSelectedRowKeys()); var retval=[]; keys.forEach(function(key){retval.push(peer.getRowIndex(key))}); return retval;";
private static final String JS_DISCLOSED_ROWS =
JS_FIND_PEER +
"var keys=Object.keys(comp.getDisclosedRowKeys()); var retval=[]; keys.forEach(function(key){retval.push(peer.getRowIndex(key))}); return retval;";
private static final String JS_GET_ROW_BY_INDEX =
JS_FIND_PEER +
"var rowinfo=peer.FindRowByKey(peer.getRowIndex(arguments[1])); if (rowinfo){return rowinfo.tr}else{return null}";
private static final String JS_GET_ROW_COUNT = JS_FIND_PEER + "return peer.GetRowCount();";
public AdfTable(WebDriver webDriver, String clientid) {
super(webDriver, clientid);
}
public <T extends AdfComponent> T findAdfComponent(String relativeClientId, String rowKey) {
String clientid =
(String) executeScript(JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWKEY, getClientId(), relativeClientId, rowKey);
if (clientid == null) {
return null;
}
return AdfComponent.forClientId(getDriver(), clientid);
}
public <T extends AdfComponent> T findAdfComponent(String relativeClientId, int rowIndex) {
scrollToRowIndex(rowIndex); // scroll to row (and possibly fetch additional data)
String clientid =
(String) executeScript(JS_FIND_RELATIVE_COMPONENT_CLIENTID_ROWINDEX, getClientId(), relativeClientId,
rowIndex);
if (clientid == null) {
return null;
}
T retval = AdfComponent.forClientId(getDriver(), clientid);
// TODO; would be niced to use TablePeer.scrollColumnIntoView but we haven't figured out a way to
// determine column index for a component
retval.scrollIntoView();
return retval;
}
public List<Integer> getSelectedRows() {
return rowIndices((List<Long>) executeScript(JS_SELECTED_ROWS, getClientId()));
}
public List<Integer> getDisclosedRows() {
return rowIndices((List<Long>) executeScript(JS_DISCLOSED_ROWS, getClientId()));
}
private List<Integer> rowIndices(List<Long> longs) {
List<Integer> retval = new ArrayList<Integer>(longs.size());
for (Long l : longs) {
retval.add(l.intValue());
}
return retval;
}
public boolean isRowDisclosed(int rowIndex) {
scrollToRowIndex(rowIndex);
String rowkey = getRowKey(rowIndex);
return (Boolean) executeScript(JS_IS_ROW_DISCLOSED, getClientId(), rowkey);
}
public void discloseRowDetail(int rowIndex) {
scrollToRowIndex(rowIndex); // scroll the table rows
WebElement link = findDisclosureLink(rowIndex);
if (link != null) {
scrollIntoView(link); // scroll the browser document
link.click();
waitForPpr();
}
}
public void scrollToRowIndex(int rowIndex) {
// could also accept a callback function
executeScript(JS_SCROLLTO_ROWINDEX, getClientId(), rowIndex);
waitForPpr();
}
public String getFocusedRowKey() {
return (String) executeScript(JS_GET_FOCUSED_ROWKEY, getClientId());
}
/**
* Returns the rowKey to identify a row based on its index. There is no guarantee that a row identified by a
* rowKey can be found on the client since all the rows are not rendered on the client. Also keep in mind that
* the rowKey on the client is not the same as the one on the server, since the server provides a mechanism for
* converting client row keys into server row keys.
* @param index the rowIndex of the row
* @return the rowKey to identify a row if found otherwise null
*/
public String getRowKey(int index) {
return (String) executeScript(JS_GET_ROWKEY, getClientId(), index);
}
/**
* Returns the index of a row identified by rowKey. There is no guarantee that a row identified by a
* rowKey can be found on the client since all the rows are not rendered on the client. Also keep in mind that
* the rowKey on the client is not the same as the one on the server, since the server provides a mechanism for
* converting client row keys into server row keys.
* @param rowKey the client side rowKey that identifies the row
* @return the index of a row for a row key if it is found otherwise -1
*/
public int getRowIndex(String rowKey) {
return ((Number) executeScript(JS_GET_ROWINDEX, getClientId(), rowKey)).intValue();
}
public long getRowCount() {
return ((Number) executeScript(JS_GET_ROW_COUNT, getClientId())).longValue();
}
public void selectRow(int index) {
scrollToRowIndex(index);
WebElement row = findRow(index);
row.click();
waitForPpr();
}
public void selectToRow(int index) {
scrollToRowIndex(index);
WebElement row = findRow(index);
new Actions(getDriver()).keyDown(Keys.SHIFT).click(row).keyUp(Keys.SHIFT).perform();
waitForPpr();
}
public void selectAdditionalRow(int index) {
scrollToRowIndex(index);
WebElement row = findRow(index);
final Keys key = isPlatform(Platform.MAC) ? Keys.COMMAND : Keys.CONTROL;
new Actions(getDriver()).keyDown(key).click(row).keyUp(key).perform();
waitForPpr();
}
protected WebElement findDisclosureLink(int index) {
// warning: when a row is disclosed all rows lower in the tabel cannot be found due to a bug in
// AdfDhtmlTableBasePeer.convertLocatorToClientId which doesn't account for the extra <tr> row
// injected by the disclosed detailStamp
return findSubIdElement("[" + index + "]" + SUBID_disclosureID);
}
protected WebElement findRow(int index) {
return (WebElement) executeScript(JS_GET_ROW_BY_INDEX, getClientId(), String.valueOf(index));
}
}