org.aludratest.service.gui.web.selenium.selenium2.Selenium2Facade.java Source code

Java tutorial

Introduction

Here is the source code for org.aludratest.service.gui.web.selenium.selenium2.Selenium2Facade.java

Source

/*
 * Copyright (C) 2010-2014 Hamburg Sud and the contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aludratest.service.gui.web.selenium.selenium2;

import static org.openqa.selenium.support.ui.ExpectedConditions.elementToBeClickable;
import static org.openqa.selenium.support.ui.ExpectedConditions.invisibilityOfElementLocated;
import static org.openqa.selenium.support.ui.ExpectedConditions.presenceOfElementLocated;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.aludratest.exception.AutomationException;
import org.aludratest.exception.PerformanceFailure;
import org.aludratest.exception.TechnicalException;
import org.aludratest.service.gui.web.selenium.SeleniumWrapperConfiguration;
import org.aludratest.service.locator.Locator;
import org.aludratest.service.locator.element.GUIElementLocator;
import org.aludratest.service.locator.element.IdLocator;
import org.aludratest.service.locator.option.IndexLocator;
import org.aludratest.service.locator.option.OptionLocator;
import org.aludratest.service.locator.window.TitleLocator;
import org.aludratest.service.locator.window.WindowLocator;
import org.aludratest.service.util.ServiceUtil;
import org.aludratest.util.data.helper.DataMarkerCheck;
import org.apache.commons.io.IOUtils;
import org.databene.commons.CollectionUtil;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.NoSuchWindowException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.StaleElementReferenceException;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.ErrorHandler.UnknownServerException;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.thoughtworks.selenium.SeleniumException;

/**
 * Wraps an instance of Selenium's {@link WebDriver} class (Selenium 2.x)
 * and provides delegation methods.
 * @author Volker Bergmann
 */
public class Selenium2Facade {

    private static final Logger LOGGER = LoggerFactory.getLogger(Selenium2Facade.class);

    // constants ---------------------------------------------------------------

    private static final int SECOND_MILLIS = 1000;

    private static final int MAX_RETRIES_ON_STALE_ELEMENT = 3;

    private static final String HAS_FOCUS_SCRIPT = "return arguments[0] == window.document.activeElement";

    // @formatter:off
    private static final String FIRE_ONCHANGE_SCRIPT = "var element = arguments[0]; var event; "
            + "if (document.createEvent) {" + "    event = document.createEvent(\"HTMLEvents\");"
            + "    event.initEvent(\"change\", true, false);" + "  } else {"
            + "    event = document.createEventObject();" + "    event.eventType = \"change\";" + "  }"
            + "  event.eventName = \"change\";" + "  if (document.createEvent) {"
            + "    element.dispatchEvent(event);" + "  } else {"
            + "    element.fireEvent(\"on\" + event.eventType, event);" + "  }";
    // @formatter:on

    private static final String DROPDOWN_OPTION_VALUE_PROPERTY = "value";
    private static final String DROPDOWN_OPTION_LABEL_PROPERTY = "text";

    private static final Set<String> EDITABLE_ELEMENTS = CollectionUtil.toSet("input", "textarea", "select", "a");

    // attributes --------------------------------------------------------------

    private SeleniumWrapperConfiguration configuration;

    private WebDriver driver;

    private ZIndexSupport zIndexSupport;

    private WebElement highlightedElement;

    private URL seleniumUrl;

    // constructor -------------------------------------------------------------

    public Selenium2Facade(SeleniumWrapperConfiguration configuration, String seleniumUrl)
            throws MalformedURLException {
        this.configuration = configuration;
        this.seleniumUrl = new URL(seleniumUrl + "/wd/hub");
        this.driver = newDriver();
        this.zIndexSupport = new ZIndexSupport(driver);
    }

    /** Creates an instance of the web driver configured in the configuration file. */
    private WebDriver newDriver() {
        try {
            String driverName = configuration.getDriverName();
            Selenium2Driver driverEnum = Selenium2Driver.valueOf(driverName);

            if (configuration.isUsingRemoteDriver()) {
                return driverEnum.newRemoteDriver(seleniumUrl);
            } else {
                return driverEnum.newLocalDriver();
            }
        } catch (Exception e) {
            throw new TechnicalException("WebDriver creation failed: ", e);
        }
    }

    // interface ---------------------------------------------------------------

    public void selectWindow(String windowId) {
        removeHighlight();
        driver.switchTo().window(windowId);
    }

    public void close() {
        try {
            driver.close();
        } catch (WebDriverException e) {
            // ignore this
        }
    }

    public void quit() {
        driver.quit();
    }

    public void open(String url) {
        try {
            driver.get(url);
        } catch (SeleniumException e) {
            String message = e.getMessage();
            if (message != null && message.contains("Timed out")) {
                throw new PerformanceFailure("Timed out opening '" + url + "': " + e);
            }
        }
    }

    public void refresh() {
        driver.navigate().refresh();
    }

    private void removeHighlight() {
        if (configuration.getHighlightCommands() && this.highlightedElement != null) {
            try {
                executeScript(
                        "arguments[0].className = arguments[0].className.replace( /(?:^|\\s)selenium-highlight(?!\\S)/g , '' ); return arguments[0].className;",
                        highlightedElement);
            } catch (WebDriverException e) {
                LOGGER.trace("Highlight remove failed. ", e);
            }
        }
    }

    private void checkHighlightCss() {
        // check if our hidden element is present
        try {
            findElement(new IdLocator("__aludra_selenium_hidden"), 1000);
        } catch (Exception e) {
            // add CSS and element
            executeScript(
                    "var css = document.createElement('style'); css.setAttribute('id', '__aludra_selenium_css'); css.setAttribute('type', 'text/css'); css.innerHTML = '.selenium-highlight { border: 3px solid red !important; }'; document.getElementsByTagName('head')[0].appendChild(css);");
            // add hidden element
            executeScript(
                    "var hidden = document.createElement('div'); hidden.setAttribute('id', '__aludra_selenium_hidden'); hidden.setAttribute('style', 'display:none;'); document.getElementsByTagName('body')[0].appendChild(hidden);");
        }
    }

    public void highlight(GUIElementLocator locator) {
        if (configuration.getHighlightCommands()) {
            try {
                removeHighlight();

                // ensure that current document has highlight CSS class
                checkHighlightCss();

                WebElement elementToHighlight = findElement(locator);
                executeScript("arguments[0].className +=' selenium-highlight'", elementToHighlight);
                this.highlightedElement = elementToHighlight;
            } catch (WebDriverException e) {
                // It does not matter if highlighting works or not, why a
                // possibly thrown exception must be caught to avoid test
                // execution termination.
                LOGGER.trace("Highlighting failed. ", e);
            }
        }
    }

    public void click(GUIElementLocator locator) {
        WebElement element = findElement(locator);
        try {
            element.click();
        } catch (Exception e) {
            handleSeleniumException(e);
        }
    }

    public boolean isEditable(GUIElementLocator locator) {
        return isEditable(findElement(locator));
    }

    public boolean isElementPresent(GUIElementLocator elementLocator) {
        try {
            findElement(elementLocator);
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }

    public boolean isInForeground(GUIElementLocator locator) {
        StaleElementReferenceException exception = null;
        // try to get z order up to 3 times
        for (int i = 0; i < MAX_RETRIES_ON_STALE_ELEMENT; i++) {
            try {
                waitUntilPresent(locator);

                WebElement element = findElement(locator);
                // on success, return the value...
                return zIndexSupport.isInForeground(element);
            } catch (StaleElementReferenceException e) {
                // ... on failure, catch and store the exception...
                exception = e;
                // and repeat (or finish) the loop
            }
        }
        // code has repeatedly failed, so forward the last exception
        throw exception;
    }

    public void setValue(GUIElementLocator locator, String value) {
        WebElement element = findElement(locator);
        String id = element.getAttribute("id");
        String fieldType = element.getAttribute("type");
        boolean fallback = true;
        if (!DataMarkerCheck.isNull(id) || "file".equals(fieldType)) {
            executeScript("document.getElementById('" + id + "').setAttribute('value', '"
                    + value.replace("'", "\\'") + "')");
            // validate success
            if (value.equals(element.getAttribute("value"))) {
                fallback = false;
                executeScript(FIRE_ONCHANGE_SCRIPT, element);
            }
        }

        // fallback code
        if (fallback) {
            element.sendKeys(Keys.END);
            String text;
            while (!DataMarkerCheck.isNull(text = element.getAttribute("value"))) {
                int length = text.length();
                String[] arr = new String[length];
                for (int i = 0; i < length; i++) {
                    arr[i] = "\b";
                }
                element.sendKeys(arr);
            }
            element.sendKeys(value);
        }
    }

    public void sendKeys(GUIElementLocator locator, String keys) {
        findElement(locator).sendKeys(keys);
    }

    public void select(GUIElementLocator locator, OptionLocator optionLocator) {
        WebElement element = findElement(locator);
        Select select = new Select(element);
        if (optionLocator instanceof org.aludratest.service.locator.option.LabelLocator) {
            select.selectByVisibleText(optionLocator.toString());
        } else if (optionLocator instanceof IndexLocator) {
            select.selectByIndex(((IndexLocator) optionLocator).getIndex());
        } else {
            throw ServiceUtil.newUnsupportedLocatorException(optionLocator);
        }
    }

    public Object getText(GUIElementLocator locator) {
        return findElement(locator).getText();
    }

    public boolean isChecked(GUIElementLocator locator) {
        return findElement(locator).isSelected();
    }

    public String[] getSelectOptions(GUIElementLocator locator) {
        WebElement element = findElement(locator);
        Select select = new Select(element);
        List<WebElement> options = select.getOptions();
        String[] labels = new String[options.size()];
        for (int i = 0; i < options.size(); i++) {
            labels[i] = options.get(i).getText();
        }
        return labels;
    }

    public Object getSelectedValue(GUIElementLocator locator) {
        Select select = new Select(findElement(locator));
        return select.getFirstSelectedOption().getText();
    }

    public Object isVisible(GUIElementLocator locator) {
        return findElement(locator).isDisplayed();
    }

    public String getSelectedLabel(GUIElementLocator locator) {
        WebElement element = findElement(locator);
        Select select = new Select(element);
        return select.getFirstSelectedOption().getText();
    }

    public String getValue(GUIElementLocator locator) {
        return findElement(locator).getAttribute("value");
    }

    public void selectWindow(WindowLocator locator) {
        if (locator instanceof TitleLocator) {
            String requestedTitle = locator.toString();

            // performance tweak: if the current window is the requested one, return immediately
            try {
                if (requestedTitle.equals(driver.getTitle())) {
                    return;
                }
            } catch (NoSuchWindowException e) {
                // this happens, when trying to call getTitle()
                // on a driver which has just close()d the recent window.
                // In this case, I fall back to iterating all windows below
            }

            removeHighlight();

            // iterate all windows and return the one with the desired title
            for (String handle : getWindowHandles()) {
                try {
                    String title = driver.switchTo().window(handle).getTitle();
                    if (requestedTitle.equals(title)) {
                        return;
                    }
                } catch (NoSuchWindowException e) {
                    // ignore; window has been removed in the meantime
                }
            }

            // if the window has not been found, throw an ElementNotFoundException
            throw new AutomationException("Element not found");
        } else {
            throw ServiceUtil.newUnsupportedLocatorException(locator);
        }
    }

    public String[] getAllWindowIDs() {
        Set<String> handles = getWindowHandles();
        return handles.toArray(new String[handles.size()]);
    }

    public String[] getAllWindowTitles() {
        Map<String, String> handlesAndTitles = getAllWindowHandlesAndTitles();
        Collection<String> titles = handlesAndTitles.values();
        LOGGER.debug("getAllWindowTitles() -> {}", titles);
        return titles.toArray(new String[handlesAndTitles.size()]);
    }

    public Map<String, String> getAllWindowHandlesAndTitles() {
        Map<String, String> handlesAndTitles = new HashMap<String, String>();
        // store handle and title of current window
        String initialWindowHandle = driver.getWindowHandle();
        String title = driver.getTitle();
        handlesAndTitles.put(initialWindowHandle, title);
        // iterate all other windows by handle and get their titles
        String currentHandle = initialWindowHandle;
        Set<String> handles = getWindowHandles();
        for (String handle : handles) {
            if (!handle.equals(initialWindowHandle)) {
                LOGGER.debug("Switching to window with handle {}", handle);
                try {
                    driver.switchTo().window(handle);
                    currentHandle = handle;
                    handlesAndTitles.put(handle, driver.getTitle());
                } catch (NoSuchWindowException e) {
                    // ignore this window
                }
                LOGGER.debug("Window with handle {} has title '{}'", handle, title);
            }
        }
        // switch back to the original window
        if (!currentHandle.equals(initialWindowHandle)) {
            driver.switchTo().window(initialWindowHandle);
        }
        return handlesAndTitles;
    }

    public String[] getAllWindowNames() {
        String current = driver.getWindowHandle();
        List<String> names = new ArrayList<String>();
        for (String handle : getWindowHandles()) {
            driver.switchTo().window(handle);
            names.add(executeScript("return window.name").toString());
        }
        driver.switchTo().window(current);
        return names.toArray(new String[names.size()]);
    }

    public String getTitle() {
        return driver.getTitle();
    }

    public String getWindowHandle() {
        return driver.getWindowHandle();
    }

    public void windowMaximize() {
        driver.manage().window().maximize();
    }

    public void windowFocus() {
        executeScript("window.focus()");
    }

    public void switchToIFrame(Locator iframeLocator) {
        if (iframeLocator == null) {
            driver.switchTo().defaultContent();
        } else {
            driver.switchTo().frame(findElement(iframeLocator));
        }
    }

    public String getHtmlSource() {
        return driver.getPageSource();
    }

    public String captureScreenshotToString() {
        // use Selenium1 interface to capture full screen
        String url = seleniumUrl.toString();
        Pattern p = Pattern.compile("(http(s)?://.+)/wd/hub(/?)");
        Matcher matcher = p.matcher(url);
        if (matcher.matches()) {
            String screenshotUrl = matcher.group(1);
            screenshotUrl += (screenshotUrl.endsWith("/") ? "" : "/")
                    + "selenium-server/driver/?cmd=captureScreenshotToString";
            InputStream in = null;
            try {
                in = new URL(screenshotUrl).openStream();
                in.read(new byte[3]); // read away "OK,"
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                IOUtils.copy(in, baos);
                return new String(baos.toByteArray(), "UTF-8");
            } catch (IOException e) {
                // OK, fallthrough to Selenium 2 method
            } finally {
                IOUtils.closeQuietly(in);
            }
        }

        WebDriver screenshotDriver;
        if (RemoteWebDriver.class.isAssignableFrom(driver.getClass())) {
            screenshotDriver = new Augmenter().augment(driver);
        } else {
            screenshotDriver = driver;
        }
        if (screenshotDriver instanceof TakesScreenshot) {
            TakesScreenshot tsDriver = (TakesScreenshot) screenshotDriver;
            return tsDriver.getScreenshotAs(OutputType.BASE64);
        } else {
            throw new UnsupportedOperationException(driver.getClass() + " does not implement TakeScreenshot");
        }
    }

    public boolean hasFocus(Locator locator) {
        WebElement element = findElement(locator);
        return (Boolean) executeScript(HAS_FOCUS_SCRIPT, element);
    }

    public void focus(GUIElementLocator locator) {
        WebElement element = findElement(locator);
        if (!isEditable(element)) {
            throw new AutomationException("Element not editable.");
        }
        executeScript("arguments[0].focus()", element);
    }

    public String[] getDropDownValues(GUIElementLocator locator) {
        return getPropertyValues(locator, DROPDOWN_OPTION_VALUE_PROPERTY);
    }

    public String[] getDropDownLabels(GUIElementLocator locator) {
        return getPropertyValues(locator, DROPDOWN_OPTION_LABEL_PROPERTY);
    }

    public String getAttributeValue(GUIElementLocator locator, String attributeName) {
        return findElement(locator).getAttribute(attributeName);
    }

    public void keyPress(int keycode) {
        driver.switchTo().activeElement().sendKeys(String.valueOf((char) keycode));
    }

    public void doubleClick(GUIElementLocator locator) {
        WebElement element = findElement(locator);
        new Actions(driver).doubleClick(element).build().perform();
    }

    public String getTable(GUIElementLocator locator, int row, int col) {
        WebElement table = findElement(locator);
        List<WebElement> tbodies = table.findElements(By.tagName("tbody"));
        WebElement rowHolder = (tbodies.size() > 0 ? tbodies.get(0) : table);
        List<WebElement> trs = rowHolder.findElements(By.tagName("tr"));
        if (row >= trs.size()) {
            throw new AutomationException(
                    "Table cell not found. " + "Requested row index " + row + " of " + trs.size() + " rows ");
        }
        List<WebElement> tds = trs.get(row).findElements(By.tagName("td"));
        if (col >= tds.size()) {
            throw new AutomationException(
                    "Table cell not found. " + "Requested column index " + col + " of " + tds.size() + " cells ");
        }
        return tds.get(col).getText();
    }

    // private helpers -------------------------------------------------------------------------------------------------

    private void handleSeleniumException(Throwable e) {
        String message = e.getMessage();

        // check if there is a WebDriverException
        WebDriverException wde = null;
        while (e != null) {
            if (e instanceof WebDriverException) {
                wde = (WebDriverException) e;
                break;
            }
            e = e.getCause();
        }

        if (wde != null) {
            // "not clickable" exception
            Pattern p = Pattern.compile("(unknown error: )?(.* not clickable .*)");
            Matcher m;
            if (message != null && (m = p.matcher(message)).find() && m.start() == 0) {
                throw new AutomationException(m.group(2), wde);
            }

            throw wde;
        }
    }

    private Object executeScript(String script, Object... arguments) {
        return ((JavascriptExecutor) driver).executeScript(script, arguments);
    }

    private boolean isEditable(WebElement element) {
        for (int i = 0; i < MAX_RETRIES_ON_STALE_ELEMENT; i++) {
            try {
                if (!element.isEnabled()) {
                    return false;
                }
                String tagName = element.getTagName().toLowerCase();
                if (!EDITABLE_ELEMENTS.contains(tagName)) {
                    return false;
                }
                if ("input".equals(tagName)) {
                    String readonly = element.getAttribute("readonly");
                    return (readonly == null || "false".equals(readonly));
                } else {
                    return true;
                }
            } catch (StaleElementReferenceException e) {
                // ignore this and retry in the next loop iteration
            }
        }

        // assert that it is gone forever. This means "not editable".
        return false;
    }

    private String[] getPropertyValues(GUIElementLocator locator, String propertyName) {
        WebElement element = findElement(locator);
        Select select = new Select(element);
        List<WebElement> options = select.getOptions();
        ArrayList<String> values = new ArrayList<String>();
        for (WebElement option : options) {
            String value = option.getAttribute(propertyName);
            if (value != null) {
                values.add(value);
            }
        }
        return values.toArray(new String[values.size()]);
    }

    public void waitUntilClickable(GUIElementLocator locator) {
        waitUntilClickable(locator, configuration.getTimeout());
    }

    public void waitUntilClickable(GUIElementLocator locator, long timeOutInMillis) {
        try {
            waitFor(elementToBeClickable(LocatorUtil.by(locator)), timeOutInMillis);
        } catch (TimeoutException e) {
            throw new AutomationException("Element not editable."); // NOSONAR
        }
    }

    public void waitUntilPresent(GUIElementLocator locator) {
        waitUntilPresent(locator, configuration.getTimeout());
    }

    public void waitUntilPresent(GUIElementLocator locator, long timeout) {
        try {
            waitFor(presenceOfElementLocated(LocatorUtil.by(locator)), timeout);
        } catch (TimeoutException e) {
            throw new AutomationException("Element not found"); //NOSONAR
        }
    }

    public void waitUntilNotPresent(GUIElementLocator locator, long timeout) {
        try {
            waitFor(AludraTestExpectedConditions.noPresenceOfElementLocated(LocatorUtil.by(locator)), timeout);
        } catch (TimeoutException e) {
            throw new AutomationException("An element was unexpectedly found"); // NOSONAR
        }
    }

    public void waitUntilVisible(GUIElementLocator locator) {
        waitUntilVisible(locator, configuration.getTimeout());
    }

    public void waitUntilVisible(GUIElementLocator locator, long timeOutInMillis) {
        try {
            waitFor(visibilityOfElementLocated(LocatorUtil.by(locator)), timeOutInMillis);
        } catch (TimeoutException e) {
            throw new AutomationException("The element is not visible."); // NOSONAR
        }
    }

    public void waitUntilInvisible(GUIElementLocator locator) {
        try {
            waitFor(invisibilityOfElementLocated(LocatorUtil.by(locator)), configuration.getTimeout());
        } catch (TimeoutException e) {
            throw new AutomationException("The element is still visible."); // NOSONAR
        }
    }

    public void waitUntilInForeground(final GUIElementLocator locator, long timeout) {
        try {
            waitFor(new ExpectedCondition<WebElement>() {
                @Override
                public WebElement apply(WebDriver input) {
                    try {
                        return isInForeground(locator) ? findElement(locator) : null;
                    } catch (WebDriverException e) {
                        return null;
                    }
                }
            }, timeout);
        } catch (TimeoutException e) {
            throw new AutomationException("The element is not in foreground.");
        }
    }

    private void waitFor(ExpectedCondition<?> condition, long timeOutInMillis) {
        long timeoutInSeconds = (timeOutInMillis + SECOND_MILLIS - 1) / SECOND_MILLIS;
        int sleepInMillis = configuration.getPauseBetweenRetries();
        WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds, sleepInMillis);
        wait.ignoring(UnknownServerException.class);
        wait.until(condition);
    }

    private WebElement findElement(Locator locator) {
        return findElement(locator, configuration.getTimeout());
    }

    private WebElement findElement(Locator locator, long timeout) {
        try {
            this.driver.manage().timeouts().implicitlyWait(timeout, TimeUnit.MILLISECONDS);
            return LocatorUtil.findElement(locator, driver);
        } catch (NoSuchElementException e) {
            throw new AutomationException("Element could not be found.", e);
        } finally {
            this.driver.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
        }
    }

    private Set<String> getWindowHandles() {
        Set<String> handles = driver.getWindowHandles();
        LOGGER.debug("getWindowHandles() -> {}", handles);
        return handles;
    }

    private static class AludraTestExpectedConditions {

        private AludraTestExpectedConditions() {
        }

        private static ExpectedCondition<Boolean> noPresenceOfElementLocated(final By locator) {
            return new ExpectedCondition<Boolean>() {
                @Override
                public Boolean apply(WebDriver input) {
                    try {
                        WebElement elem = input.findElement(locator);
                        return Boolean.valueOf(elem == null);
                    } catch (NoSuchElementException e) {
                        return Boolean.TRUE;
                    }
                }
            };
        }

    }

}