wffweb/src/main/java/com/webfirmframework/wffweb/tag/repository/TagRepository.java
public static AbstractHtml findOneTagByAttribute(final boolean parallel,
            final String attributeName, final String attributeValue,
            final AbstractHtml... fromTags) throws NullValueException {

        if (attributeName == null) {
            throw new NullValueException(
                    "The attributeName should not be null");
        }
        if (attributeValue == null) {
            throw new NullValueException(
                    "The attributeValue should not be null");
        }

        if (fromTags == null) {
            throw new NullValueException("The fromTags should not be null");
        }

        final Collection<Lock> locks = getReadLocks(fromTags);
        for (final Lock lock : locks) {
            lock.lock();
        }

        try {
            final Stream<AbstractHtml> stream = getAllNestedChildrenIncludingParent(
                    parallel, fromTags);

            final Optional<AbstractHtml> any = stream.filter(child -> {

                final AbstractAttribute attr = child
                        .getAttributeByName(attributeName);

                return attr != null
                        && attributeValue.equals(attr.getAttributeValue());

            }).findAny();

            if (any.isPresent()) {
                return any.get();
            }
            return null;
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
public static AbstractHtml findOneTagByAttribute(final boolean parallel,
            final String attributeName, final String attributeValue,
            final AbstractHtml... fromTags) throws NullValueException {

        if (attributeName == null) {
            throw new NullValueException(
                    "The attributeName should not be null");
        }
        if (attributeValue == null) {
            throw new NullValueException(
                    "The attributeValue should not be null");
        }

        if (fromTags == null) {
            throw new NullValueException("The fromTags should not be null");
        }

        final Collection<Lock> locks = getReadLocks(fromTags);
        for (final Lock lock : locks) {
            lock.lock();
        }

        try {
            final Stream<AbstractHtml> stream = getAllNestedChildrenIncludingParent(
                    parallel, fromTags);

            final Optional<AbstractHtml> any = stream.filter(child -> {

                final AbstractAttribute attr = child
                        .getAttributeByName(attributeName);

                return attr != null
                        && attributeValue.equals(attr.getAttributeValue());

            }).findAny();

            if (any.isPresent()) {
                return any.get();
            }
            return null;
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
Finds and returns the first (including the nested tags) matching with the
given attribute name and value.

@param attributeName
the name of the attribute.
@param attributeValue
the value of the attribute
@param fromTags
from which the findings to be done.
@return the first matching tag with the given attribute name and value.
@throws NullValueException
if the {@code attributeName},
{@code attributeValue} or {@code fromTags}
is null
@since 3.0.0
@author WFF