org.asqatasun.ruleimplementation.AbstractMarkerPageRuleImplementation.java Source code

Java tutorial

Introduction

Here is the source code for org.asqatasun.ruleimplementation.AbstractMarkerPageRuleImplementation.java

Source

/*
 * Asqatasun - Automated webpage assessment
 * Copyright (C) 2008-2015  Asqatasun.org
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact us by mail: asqatasun AT asqatasun DOT org
 */
package org.asqatasun.ruleimplementation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import javax.annotation.Nonnull;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Element;
import org.asqatasun.entity.parameterization.Parameter;
import org.asqatasun.processor.SSPHandler;
import org.asqatasun.rules.elementchecker.ElementChecker;
import org.asqatasun.rules.elementselector.ElementSelector;
import static org.asqatasun.rules.keystore.AttributeStore.ROLE_ATTR;

/**
 * This class should be overridden by concrete {@link RuleImplementation}
 * classes which implement tests with page scope.
 * <p>
 * It deals with the selection of elements identified by markers. These markers
 * correspond to a specific value of either the "id" attribute, either the
 * "class" attribute or the "role" attribute of a HTML element.</p>
 * <p>
 * Two kind of markers can be defined :
 * <ul>
 * <li>
 * Direct marker that enable to include elements into the selection and
 * determine their nature
 * </li>
 * <li>
 * Inverse marker that identify elements of same type but with another nature.
 * These elements have to be excluded from the selection
 * </li>
 * </ul>
 * </p>
 *
 */
public abstract class AbstractMarkerPageRuleImplementation
        extends AbstractPageRuleWithSelectorAndCheckerImplementation {

    /**
     * The elements identified with the markers
     */
    private final ElementHandler<Element> selectionWithMarkerHandler = new ElementHandlerImpl();

    public ElementHandler<Element> getSelectionWithMarkerHandler() {
        return selectionWithMarkerHandler;
    }

    /**
     * The elements not identified by the markers
     */
    private final ElementHandler<Element> selectionWithoutMarkerHandler = new ElementHandlerImpl();

    public ElementHandler<Element> getSelectionWithoutMarkerHandler() {
        return selectionWithoutMarkerHandler;
    }

    /**
     * The marker codes that identifies the targeted elements
     */
    private final String[] markerCodes;

    /**
     * The marker codes that identifies elements of same type but with another
     * nature.
     */
    private final String[] inverseMarkerCodes;

    /**
     * The collection of marker that enable to identify the targeted elements
     */
    private final Collection<String> markerList = new HashSet<>();

    /**
     * The collection of marker that enable to identify elements of the same
     * type but with another nature.
     */
    private final Collection<String> inverseMarkerList = new HashSet<>();

    /**
     * The elementChecker used by the rule for marker elements
     */
    private ElementChecker markerElementChecker;

    public void setMarkerElementChecker(ElementChecker markerElementChecker) {
        this.markerElementChecker = markerElementChecker;
    }

    /**
     * The elementChecker used by the rule for regular elements, i.e not 
     * identified by marker
     * @return 
     */
    public ElementChecker getRegularElementChecker() {
        return getElementChecker();
    }

    public final void setRegularElementChecker(ElementChecker regularElementChecker) {
        this.setElementChecker(regularElementChecker);
    }

    /**
     * Constructor
     *
     * @param markerCode
     * @param inverseMarkerCode
     */
    public AbstractMarkerPageRuleImplementation(@Nonnull String markerCode, @Nonnull String inverseMarkerCode) {
        this(new String[] { markerCode }, new String[] { inverseMarkerCode });
    }

    /**
     * Constructor
     *
     * @param markerCode
     * @param inverseMarkerCode
     */
    public AbstractMarkerPageRuleImplementation(@Nonnull String[] markerCode, @Nonnull String[] inverseMarkerCode) {
        super();
        this.markerCodes = markerCode;
        this.inverseMarkerCodes = inverseMarkerCode;
    }

    /**
     * Constructor
     *
     * @param elementSelector
     * @param markerCode
     * @param inverseMarkerCode
     * @param markerElementChecker
     * @param elementChecker
     */
    public AbstractMarkerPageRuleImplementation(@Nonnull ElementSelector elementSelector,
            @Nonnull String markerCode, @Nonnull String inverseMarkerCode,
            @Nonnull ElementChecker markerElementChecker, @Nonnull ElementChecker elementChecker) {
        this(elementSelector, new String[] { markerCode }, new String[] { inverseMarkerCode }, markerElementChecker,
                elementChecker);
    }

    /**
     * Constructor
     *
     * @param elementSelector
     * @param markerCode
     * @param inverseMarkerCode
     * @param markerElementChecker
     * @param regularElementChecker
     */
    public AbstractMarkerPageRuleImplementation(@Nonnull ElementSelector elementSelector,
            @Nonnull String[] markerCode, @Nonnull String[] inverseMarkerCode,
            @Nonnull ElementChecker markerElementChecker, @Nonnull ElementChecker regularElementChecker) {
        super();
        this.markerCodes = markerCode;
        this.inverseMarkerCodes = inverseMarkerCode;
        setElementSelector(elementSelector);
        this.setElementChecker(regularElementChecker);
        this.markerElementChecker = markerElementChecker;
    }

    @Override
    protected void select(SSPHandler sspHandler) {
        getElementSelector().selectElements(sspHandler, selectionWithoutMarkerHandler);
        extractMarkerListFromAuditParameter(sspHandler);
        sortMarkerElements();
    }

    @Override
    protected void check(SSPHandler sspHandler, TestSolutionHandler testSolutionHandler) {
        if (!selectionWithMarkerHandler.isEmpty()) {
            setServicesToChecker(markerElementChecker);
            markerElementChecker.check(sspHandler, selectionWithMarkerHandler, testSolutionHandler);
        }
        if (!selectionWithoutMarkerHandler.isEmpty()) {
            setServicesToChecker(getRegularElementChecker());
            getRegularElementChecker().check(sspHandler, selectionWithoutMarkerHandler, testSolutionHandler);
        }
    }

    @Override
    public int getSelectionSize() {
        return this.selectionWithoutMarkerHandler.get().size() + this.selectionWithMarkerHandler.get().size();
    }

    /**
     * Retrieves the parameter value from audit parameters and return the marker
     * list
     *
     * @param sspHandler
     */
    protected void extractMarkerListFromAuditParameter(SSPHandler sspHandler) {

        for (Parameter parameter : sspHandler.getSSP().getAudit().getParameterSet()) {
            String paramElCode = parameter.getParameterElement().getParameterElementCode();
            for (String markerCode : markerCodes) {
                if (StringUtils.equalsIgnoreCase(paramElCode, markerCode)) {
                    String markerTab = parameter.getValue();
                    if (StringUtils.isNotEmpty(markerTab)) {
                        addMarkersToList(markerTab, markerList);
                    }
                }
            }
            for (String inverseMarkerCode : inverseMarkerCodes) {
                if (StringUtils.equalsIgnoreCase(paramElCode, inverseMarkerCode)) {
                    String markerTab = parameter.getValue();
                    if (StringUtils.isNotEmpty(markerTab)) {
                        addMarkersToList(markerTab, inverseMarkerList);
                    }
                }
            }
        }
    }

    /**
     * To sort marker elements, we extract for each of them the value of the
     * "id" attribute the value of the "class" attribute and the value of the
     * "role" attribute. If one of these three values belongs to the marker
     * value list set by the user, we consider that the element is characterised
     * and we add it to the "elementMarkerList".
     *
     * @param nodeList
     */
    private void sortMarkerElements() {
        if ((CollectionUtils.isEmpty(markerList) && CollectionUtils.isEmpty(inverseMarkerList))
                || selectionWithoutMarkerHandler.isEmpty()) {
            return;
        }
        Iterator<Element> iter = selectionWithoutMarkerHandler.get().iterator();
        Element el;
        while (iter.hasNext()) {
            el = iter.next();
            String id = el.id();
            Collection<String> classNames = el.classNames();
            String role = el.attr(ROLE_ATTR);
            // if the element does contain an "id" OR a "class" attribute OR
            // a "role" attribute AND one the values belongs to the marker list, 
            // it is removed from the global selection and added to the 
            // marker element selection.
            if (StringUtils.isNotBlank(id) || CollectionUtils.isNotEmpty(classNames)
                    || StringUtils.isNotBlank(role)) {
                if (checkAttributeBelongsToMarkerList(id, classNames, role, markerList)) {
                    selectionWithMarkerHandler.add(el);
                    iter.remove();
                }
                // if the element belongs to the inverse marker list, it is
                // removed from the global collection
                if (checkAttributeBelongsToMarkerList(id, classNames, role, inverseMarkerList)) {
                    iter.remove();
                }
            }
        }
    }

    /**
     * @param id
     * @param classNames
     * @param role
     * @return whether one of the string given as argument belongs to a marker
     * list
     */
    private boolean checkAttributeBelongsToMarkerList(String id, Collection<String> classNames, String role,
            Collection<String> markerList) {
        if (CollectionUtils.isEmpty(markerList)) {
            return false;
        }
        Collection<String> elAttr = new ArrayList<>();
        elAttr.add(id);
        elAttr.addAll(classNames);
        elAttr.add(role);
        return CollectionUtils.containsAny(markerList, elAttr);
    }

    /**
     *
     * Utility method to extract marker values, and apply a trim on values set
     * by the user
     *
     * @param parameterValue
     * @param markers
     */
    private void addMarkersToList(String parameters, Collection<String> markers) {
        for (String markerValue : parameters.split(";")) {
            markers.add(markerValue.trim());
        }
    }

}