com.epam.jdi.uitests.web.selenium.elements.complex.table.Table.java Source code

Java tutorial

Introduction

Here is the source code for com.epam.jdi.uitests.web.selenium.elements.complex.table.Table.java

Source

package com.epam.jdi.uitests.web.selenium.elements.complex.table;
/*
 * Copyright 2004-2016 EPAM Systems
 *
 * This file is part of JDI project.
 *
 * JDI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JDI 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JDI. If not, see <http://www.gnu.org/licenses/>.
 */

import com.epam.commons.map.MapArray;
import com.epam.commons.pairs.Pair;
import com.epam.jdi.uitests.core.interfaces.base.ISelect;
import com.epam.jdi.uitests.core.interfaces.base.ISetup;
import com.epam.jdi.uitests.core.interfaces.complex.tables.interfaces.*;
import com.epam.jdi.uitests.web.selenium.elements.apiInteract.GetElementModule;
import com.epam.jdi.uitests.web.selenium.elements.common.Text;
import com.epam.jdi.uitests.web.selenium.elements.pageobjects.annotations.objects.JTable;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.epam.commons.EnumUtils.getAllEnumNames;
import static com.epam.commons.EnumUtils.getEnumValue;
import static com.epam.commons.LinqUtils.*;
import static com.epam.commons.PrintUtils.print;
import static com.epam.commons.Timer.waitCondition;
import static com.epam.jdi.uitests.core.settings.JDISettings.*;
import static com.epam.jdi.uitests.web.selenium.elements.pageobjects.annotations.WebAnnotationsUtil.findByToBy;
import static com.epam.jdi.uitests.web.selenium.elements.pageobjects.annotations.objects.FillFromAnnotationRules.fieldHasAnnotation;
import static java.lang.Integer.parseInt;
import static java.lang.String.format;
import static java.util.Arrays.asList;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * Created by Roman_Iovlev on 6/2/2015.
 */
public class Table extends Text implements ITable, Cloneable, ISetup {
    public boolean cache = true;
    protected List<String> footer;
    protected By cellLocatorTemplate;
    protected List<ICell> allCells = new ArrayList<>();
    protected Columns columns = new Columns();
    protected Rows rows = new Rows();
    protected By footerLocator = By.xpath(".//tfoot/tr/th");

    // ------------------------------------------ //

    public Table() {
        this(By.tagName("table"));
        //GetFooterFunc = t => t.FindElements(By.xpath("//tfoot/tr/td")).Select(el => el.Text).ToArray();
    }

    public Table(By tableLocator) {
        super(tableLocator);
        columns.table = this;
        rows.table = this;
    }

    public Table(By columnHeader, By row, By column) {
        this();
        if (column != null)
            columns.lineTemplate = column;
        if (columnHeader != null)
            columns.headersLocator = columnHeader;
        if (row != null)
            rows.lineTemplate = row;
    }

    public Table(By rowHeader, By columnHeader, By row, By column, int rowStartIndex, int columnStartIndex) {
        this();
        if (column != null)
            columns.lineTemplate = column;
        if (columnHeader != null)
            columns.headersLocator = columnHeader;
        if (row != null)
            rows.lineTemplate = row;
        if (rowHeader != null)
            rows.headersLocator = rowHeader;

        if (columnStartIndex > -1)
            columns.startIndex = columnStartIndex;
        if (rowStartIndex > -1)
            rows.startIndex = rowStartIndex;
    }

    public Table(By tableLocator, By cellLocatorTemplate) {
        this(tableLocator);
        this.cellLocatorTemplate = cellLocatorTemplate;
    }

    public Table(By columnHeader, By rowHeader, By row, By column, By footer, int columnStartIndex,
            int rowStartIndex) {
        this();

        columns.lineTemplate = column;
        if (columnHeader != null)
            columns.headersLocator = columnHeader;
        rows.lineTemplate = row;
        if (rowHeader != null)
            rows.headersLocator = rowHeader;
        footerLocator = footer;

        columns.startIndex = columnStartIndex;
        rows.startIndex = rowStartIndex;

    }

    public Table copy() {
        return clone();
    }

    public Table clone() {
        Table newTable = new Table();
        newTable.rows = ((Rows) rows()).clone(new Rows(), newTable);
        newTable.columns = ((Columns) columns()).clone(new Columns(), newTable);
        newTable.avatar = new GetElementModule(getLocator(), newTable);
        return newTable;
    }

    public List<ICell> getCells() {
        List<ICell> result = new ArrayList<>();
        for (String columnName : columns().headers())
            //it was so
            // columns().headers().forEach(rowName-> result.add(cell(columnName, rowName)))
            rows().headers().forEach(rowName -> result.add(cell(columnName, rowName)));
        if (cache)
            allCells = result;
        return result;
    }

    public void setup(Field field) {
        if (!fieldHasAnnotation(field, JTable.class, ITable.class))
            return;
        JTable jTable = field.getAnnotation(JTable.class);
        By root = findByToBy(jTable.root());
        if (root == null)
            root = findByToBy(jTable.jRoot());
        setAvatar(root);
        By headers = findByToBy(jTable.headers());
        By rowNames = findByToBy(jTable.rowNames());
        cellLocatorTemplate = findByToBy(jTable.cell());
        columns.lineTemplate = findByToBy(jTable.column());
        rows.lineTemplate = findByToBy(jTable.row());
        footerLocator = findByToBy(jTable.footer());
        columns.startIndex = jTable.colStartIndex();
        rows.startIndex = jTable.rowStartIndex();
        if (headers == null)
            headers = findByToBy(jTable.jHeaders());
        if (rowNames == null)
            rowNames = findByToBy(jTable.jRowNames());
        if (cellLocatorTemplate == null)
            cellLocatorTemplate = findByToBy(jTable.jCell());
        if (columns.lineTemplate == null)
            columns.lineTemplate = findByToBy(jTable.jColumn());
        if (rows.lineTemplate == null)
            rows.lineTemplate = findByToBy(jTable.jRow());
        if (footerLocator == null)
            footerLocator = findByToBy(jTable.jFooter());

        if (headers != null)
            columns.headersLocator = headers;
        if (rowNames != null)
            rows.headersLocator = rowNames;

        if (jTable.header().length > 0)
            hasColumnHeaders(asList(jTable.header()));
        if (jTable.rowsHeader().length > 0)
            hasRowHeaders(asList(jTable.rowsHeader()));

        if (jTable.height() > 0)
            setColumnsCount(jTable.height());
        if (jTable.width() > 0)
            setRowsCount(jTable.width());
        if (!jTable.size().equals("")) {
            String[] split = jTable.size().split("x");
            if (split.length == 1)
                split = jTable.size().split("X");
            if (split.length != 2)
                throw exception("Can't setup Table from attribute. Bad size: " + jTable.size());
            setColumnsCount(parseInt(split[0]));
            setRowsCount(parseInt(split[1]));
        }

        switch (jTable.headerType()) {
        case COLUMNS_HEADERS:
            hasOnlyColumnHeaders();
            break;
        case ROWS_HEADERS:
            hasOnlyRowHeaders();
            break;
        case ALL_HEADERS:
            hasAllHeaders();
            break;
        case NO_HEADERS:
            hasNoHeaders();
            break;
        }
        useCache(jTable.useCache());
    }

    public ITable useCache(boolean value) {
        cache = value;
        return this;
    }

    public void clean() {
        allCells = new ArrayList<>();
        columns().clean();
        rows().clean();
    }

    public void clear() {
        clean();
    }

    public IColumn columns() {
        return columns;
    }

    public MapArray<String, ICell> column(int colNum) {
        return columns().getColumn(colNum);
    }

    public MapArray<String, ICell> column(String colName) {
        return columns().getColumn(colName);
    }

    private MapArray<String, ICell> column(Column column) {
        return column.get(this::column, this::column);
    }

    public List<String> columnValue(int colNum) {
        return columns().getColumnValue(colNum);
    }

    public List<String> columnValue(String colName) {
        return columns().getColumnValue(colName);
    }

    public void setColumns(Columns value) {
        columns.update(value);
    }

    public IRow rows() {
        return rows;
    }

    public MapArray<String, ICell> row(int rowNum) {
        return rows().getRow(rowNum);
    }

    public MapArray<String, ICell> row(String rowName) {
        return rows().getRow(rowName);
    }

    private MapArray<String, ICell> row(Row row) {
        return row.get(this::row, this::row);
    }

    public List<String> rowValue(int rowNum) {
        return rows().getRowValue(rowNum);
    }

    public List<String> rowValue(String rowName) {
        return rows().getRowValue(rowName);
    }

    public void setRows(Rows value) {
        rows.update(value);
    }

    public ITable hasAllHeaders() {
        ((Columns) columns()).hasHeader = true;
        ((Rows) rows()).hasHeader = true;
        return this;
    }

    public ITable hasNoHeaders() {
        ((Columns) columns()).hasHeader = false;
        ((Rows) rows()).hasHeader = false;
        return this;
    }

    public ITable hasOnlyColumnHeaders() {
        ((Columns) columns()).hasHeader = true;
        ((Rows) rows()).hasHeader = false;
        return this;
    }

    public ITable hasOnlyRowHeaders() {
        ((Columns) columns()).hasHeader = false;
        ((Rows) rows()).hasHeader = true;
        return this;
    }

    public ITable hasColumnHeaders(List<String> value) {
        ((Columns) columns()).hasHeader = true;
        ((Columns) columns()).headers = new ArrayList<>(value);
        return this;
    }

    public <THeaders extends Enum> ITable hasColumnHeaders(Class<THeaders> headers) {
        return hasColumnHeaders(getAllEnumNames(headers));
    }

    public ITable hasRowHeaders(List<String> value) {
        ((Rows) rows()).hasHeader = true;
        ((Rows) rows()).headers = new ArrayList<>(value);
        return this;
    }

    public <THeaders extends Enum> ITable hasRowHeaders(Class<THeaders> headers) {
        return hasRowHeaders(getAllEnumNames(headers));
    }

    public ITable setColumnsCount(int value) {
        columns().setCount(value);
        return this;
    }

    public ITable setRowsCount(int value) {
        rows().setCount(value);
        return this;
    }

    protected List<String> getFooterAction() {
        return select(getWebElement().findElements(footerLocator), WebElement::getText);
    }

    private List<String> getFooter() {
        return new ArrayList<>(footer);
    }

    public void setFooter(List<String> value) {
        footer = new ArrayList<>(value);
    }

    public final MapArray<String, ISelect> header() {
        return columns().header();
    }

    public final ISelect header(String name) {
        return columns().header(name);
    }

    public final <TEnum extends Enum> ISelect header(TEnum enumName) {
        return columns().header(getEnumValue(enumName));
    }

    public List<String> headers() {
        return columns().headers();
    }

    public List<String> footer() {
        if (footer != null)
            return getFooter();
        footer = invoker.doJActionResult("Get Footer", this::getFooterAction);
        if (footer == null || footer.size() == 0)
            return new ArrayList<>();
        columns().setCount(footer.size());
        return getFooter();
    }

    public ICell cell(Column column, Row row) {
        int colIndex = column.get(this::getColumnIndex, num -> num + columns().getStartIndex() - 1);
        int rowIndex = row.get(this::getRowIndex, num -> num + rows().getStartIndex() - 1);
        return addCell(colIndex, rowIndex, column.get(name -> columns().headers().indexOf(name) + 1, num -> num),
                row.get(name -> rows().headers().indexOf(name) + 1, num -> num),
                column.get(name -> name, num -> ""), row.get(name -> name, num -> ""));
    }

    public ICell cell(WebElement webElement, Column column, Row row) {
        return addCell(webElement, column.get(name -> columns().headers().indexOf(name) + 1, num -> num),
                row.get(name -> rows().headers().indexOf(name) + 1, num -> num),
                column.get(name -> name, num -> ""), row.get(name -> name, num -> ""));
    }

    private List<ICell> contains(Collection<ICell> list, String value) {
        return new ArrayList<>(where(list, cell -> cell.getValue().contains(value)));
    }

    private List<ICell> matches(Collection<ICell> list, String regex) {
        return new ArrayList<>(where(list, cell -> cell.getValue().matches(regex)));
    }

    public List<ICell> cells(String value) {
        return new ArrayList<>(where(getCells(), cell -> cell.getValue().equals(value)));
    }

    public List<ICell> cellsContains(String value) {
        return contains(getCells(), value);
    }

    public List<ICell> cellsMatch(String regex) {
        return matches(getCells(), regex);
    }

    public ICell cell(String value) {
        ICell result;
        for (Pair<String, MapArray<String, ICell>> row : rows().get()) {
            result = row.value.first((cName, cValue) -> cValue.getText().equals(value));
            if (result != null)
                return result;
        }
        return null;
    }

    public ICell cellMatch(String regex) {
        ICell result;
        for (Pair<String, MapArray<String, ICell>> row : rows().get()) {
            result = row.value.first((cName, cValue) -> cValue.getText().matches(regex));
            if (result != null)
                return result;
        }
        return null;
    }

    public MapArray<String, MapArray<String, ICell>> rows(String value, Column column) {
        return rows().withValue(value, column);
    }

    public MapArray<String, MapArray<String, ICell>> rowsContains(String value, Column column) {
        return rows().containsValue(value, column);
    }

    public MapArray<String, MapArray<String, ICell>> rowsMatches(String regEx, Column column) {
        return rows().matchesRegEx(regEx, column);
    }

    public MapArray<String, MapArray<String, ICell>> rows(String... colNameValues) {
        if (colNameValues.length == 0)
            return rows().get();
        List<TableFilter> filters = new ArrayList<>();
        for (String colNameValue : colNameValues)
            filters.add(new TableFilter(colNameValue));
        boolean matches = false;
        MapArray<String, MapArray<String, ICell>> result = new MapArray<>();
        for (Pair<String, MapArray<String, ICell>> row : rows().get()) {
            for (TableFilter filter : filters) {
                ICell cell = row.value.get(filter.name);
                if (cell == null)
                    throw exception(format("Search rows for '%s' failed. Can't get cell for column named %s",
                            print(colNameValues), filter.name));
                switch (filter.type) {
                case EQUAL:
                    matches = cell.getValue().equals(filter.value);
                    break;
                case CONTAINS:
                    matches = cell.getValue().contains(filter.value);
                    break;
                case MATCH:
                    matches = cell.getValue().matches(filter.value);
                    break;
                }
                if (!matches)
                    break;
            }
            if (matches)
                result.add(row);
        }
        return result;
    }

    public MapArray<String, MapArray<String, ICell>> columns(String value, Row row) {
        return columns().withValue(value, row);
    }

    public MapArray<String, MapArray<String, ICell>> columnsContains(String value, Row row) {
        return columns().containsValue(value, row);
    }

    public MapArray<String, MapArray<String, ICell>> columnsMatches(String regEx, Row row) {
        return columns().matchesRegEx(regEx, row);
    }

    public MapArray<String, MapArray<String, ICell>> columns(String... rowNameValues) {
        if (rowNameValues.length == 0)
            return columns().get();
        MapArray<String, MapArray<String, ICell>> result = new MapArray<>();
        for (Pair<String, MapArray<String, ICell>> column : columns().get()) {
            boolean matches = true;
            for (String rowNameValue : rowNameValues) {
                if (!rowNameValue.matches("[^=]+=[^=]*"))
                    throw exception("Wrong searchCritaria for Cells: " + rowNameValue);
                String[] splitted = rowNameValue.split("=");
                String rowName = splitted[0];
                String rowValue = splitted[1];
                ICell cell = column.value.get(rowName);
                if (cell == null || !cell.getValue().equals(rowValue)) {
                    matches = false;
                    break;
                }
            }
            if (matches)
                result.add(column);
        }
        return result;
    }

    public boolean waitValue(String value, Row row) {
        return timer().wait(() -> column(value, row) != null);
    }

    public boolean waitValue(String value, Column column) {
        return waitCondition(() -> row(value, column) != null);
    }

    public boolean isEmpty() {
        getDriver().manage().timeouts().implicitlyWait(0, MILLISECONDS);
        int rowsCount = rows().count(true);
        getDriver().manage().timeouts().implicitlyWait(timeouts.getCurrentTimeoutSec(), SECONDS);
        return rowsCount == 0;
    }

    public boolean waitHaveRows() {
        return waitRows(1);
    }

    public boolean waitRows(int count) {
        return waitCondition(() -> rows().count() >= count);
    }

    public ICell cell(String value, Row row) {
        int rowNum = row.hasName() ? rows().headers().indexOf(row.getName()) + 1 : row.getNum();
        return rows().getRow(rowNum).first((name, cell) -> cell.getValue().equals(value));
    }

    public ICell cellContains(String value, Row row) {
        int rowNum = row.hasName() ? rows().headers().indexOf(row.getName()) + 1 : row.getNum();
        return rows().getRow(rowNum).first((name, cell) -> cell.getValue().contains(value));
    }

    public ICell cellMatch(String regex, Row row) {
        MapArray<String, ICell> rowLine = row(row);
        List<ICell> cells = matches(rowLine.values(), regex);
        if (cells.size() == 0) {
            logger.info(format("Can't find any cells in row %s that matches regEx: %s", row, regex));
            return null;
        }
        return cells.get(0);
    }

    public ICell cell(String value, Column column) {
        int colIndex = column.get(
                name -> select(columns().headers(), String::toLowerCase).indexOf(name.toLowerCase()) + 1,
                num -> num);
        return columns().getColumn(colIndex).first((name, cell) -> cell.getValue().equals(value));
    }

    public ICell cellContains(String value, Column column) {
        int colIndex = column.get(
                name -> select(columns().headers(), String::toLowerCase).indexOf(name.toLowerCase()) + 1,
                num -> num);
        return columns().getColumn(colIndex).first((name, cell) -> cell.getValue().contains(value));
    }

    public ICell cellMatch(String regex, Column column) {
        MapArray<String, ICell> columnLine = column(column);
        List<ICell> cells = matches(columnLine.values(), regex);
        if (cells.size() == 0) {
            logger.info(format("Can't find any cells in column %s that matches regEx: %s", column, regex));
            return null;
        }
        return cells.get(0);
    }

    public List<ICell> cellsMatch(String regex, Column column) {
        MapArray<String, ICell> columnLine = column(column);
        return matches(columnLine.values(), regex);
    }

    public List<ICell> cellsMatch(String regex, Row row) {
        MapArray<String, ICell> rowLine = row(row);
        return matches(rowLine.values(), regex);
    }

    public MapArray<String, ICell> column(String value, Row row) {
        ICell columnCell = cell(value, row);
        if (columnCell == null) {
            logger.info(format("Can't find any cells in row %s with value %s", row, value));
            return null;
        }
        return columns().getColumn(columnCell.columnNum());
    }

    public MapArray<String, ICell> columnContains(String value, Row row) {
        ICell columnCell = cellContains(value, row);
        if (columnCell == null) {
            logger.info(format("Can't find any cells in row %s that contains value %s", row, value));
            return null;
        }
        return columns().getColumn(columnCell.columnNum());
    }

    public MapArray<String, ICell> columnMatch(String regEx, Row row) {
        ICell columnCell = cellMatch(regEx, row);
        if (columnCell == null) {
            logger.info(format("Can't find any cells in row %s that matches regex %s", row, regEx));
            return null;
        }
        return columns().getColumn(columnCell.columnNum());
    }

    public MapArray<String, ICell> row(String value, Column column) {
        ICell rowCell = cell(value, column);
        if (rowCell == null) {
            logger.info(format("Can't find any cells in column %s with value %s", column, value));
            return null;
        }
        return rows().getRow(rowCell.rowNum());
    }

    public MapArray<String, ICell> rowContains(String value, Column column) {
        ICell rowCell = cellContains(value, column);
        if (rowCell == null) {
            logger.info(format("Can't find any cells in column %s that contains value %s", column, value));
            return null;
        }
        return rows().getRow(rowCell.rowNum());
    }

    public MapArray<String, ICell> rowMatch(String regEx, Column column) {
        ICell rowCell = cellMatch(regEx, column);
        if (rowCell == null) {
            logger.info(format("Can't find any cells in column %s that matches regEx: %s", column, regEx));
            return null;
        }
        return rows().getRow(rowCell.rowNum());
    }

    private int getColumnIndex(String name) {
        int nameIndex;
        List<String> headers = select(columns().headers(), String::toLowerCase);
        String lName = name.toLowerCase();
        if (headers != null && headers.contains(lName))
            nameIndex = headers.indexOf(lName);
        else
            throw exception("Can't Get Column: '" + name + "'. " + ((headers == null) ? "ColumnHeaders is Null"
                    : ("Available ColumnHeaders: " + print(headers, ", ", "'%s'") + ")")));
        return nameIndex + columns().getStartIndex();
    }

    private int getRowIndex(String name) {
        int nameIndex;
        List<String> headers = select(rows().headers(), String::toLowerCase);
        String lName = name.toLowerCase();
        if (headers != null && headers.contains(lName))
            nameIndex = headers.indexOf(lName);
        else
            throw exception("Can't Get Row: '%s'. Available RowHeaders: (%s)", name, print(headers, ", ", "'%s'"));
        return nameIndex + rows().getStartIndex();
    }

    @Override
    protected String getTextAction() {
        return "||X||" + print(columns().headers(), "|") + "||\n" + print(
                select(rows().headers(), rowName -> "||" + rowName + "||" + print(rowValue(rowName), "|") + "||"),
                "\n");
    }

    private Cell addCell(int colIndex, int rowIndex, int colNum, int rowNum, String colName, String rowName) {
        Cell cell = (allCells.size() != 0)
                ? (Cell) first(allCells, c -> c.columnNum() == colNum && c.rowNum() == rowNum)
                : null;
        if (cell != null)
            return cell.updateData(colName, rowName);
        cell = new Cell(colIndex, rowIndex, colNum, rowNum, colName, rowName, cellLocatorTemplate, this);
        cell.setParent(this);
        if (cache)
            allCells.add(cell);
        return cell;
    }

    private Cell addCell(WebElement webElement, int colNum, int rowNum, String colName, String rowName) {
        Cell cell = (Cell) first(allCells, c -> c.columnNum() == colNum && c.rowNum() == rowNum);
        if (cell != null) {
            cell.setWebElement(webElement);
            return cell.updateData(colName, rowName);
        }
        cell = new Cell(webElement, colNum, rowNum, colName, rowName, cellLocatorTemplate, this);
        if (cache)
            allCells.add(cell);
        return cell;
    }
}