wffweb/src/main/java/com/webfirmframework/wffweb/tag/repository/TagRepository.java
public Collection<AbstractHtml> findTagsByAttribute(final boolean parallel,
            final String attributeName, final String attributeValue)
            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");
        }

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

        try {
            return buildAllTagsStream(parallel).filter(tag -> {

                final AbstractAttribute attribute = tag
                        .getAttributeByName(attributeName);

                return attribute != null
                        && attributeValue.equals(attribute.getAttributeValue());
            }).collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
public Collection<AbstractHtml> findTagsByAttribute(final boolean parallel,
            final String attributeName, final String attributeValue)
            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");
        }

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

        try {
            return buildAllTagsStream(parallel).filter(tag -> {

                final AbstractAttribute attribute = tag
                        .getAttributeByName(attributeName);

                return attribute != null
                        && attributeValue.equals(attribute.getAttributeValue());
            }).collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
Finds and returns the collection of tags (including the nested tags)
matching with the given attribute name and value.

@param parallel
true to internally use parallel stream. If true
it will split the finding task to different
batches and will execute the batches in
different threads in parallel consuming all
CPUs. It will perform faster in finding from
extremely large number of tags but at the same
time it will less efficient in finding from
small number of tags.
@param attributeName
the name of the attribute.
@param attributeValue
the value of the attribute
@return the collection of tags matching with the given attribute name and
value.
@throws NullValueException
if the {@code attributeName} or
{@code attributeValue} is null
@since 3.0.0
@author WFF