wffweb/src/main/java/com/webfirmframework/wffweb/tag/repository/TagRepository.java
public static Collection<AbstractAttribute> findAttributesByAttributeFilter(
            final boolean parallel,
            final Predicate<? super AbstractAttribute> filter,
            final AbstractHtml... fromTags) throws NullValueException {

        if (filter == null) {
            throw new NullValueException("The tagName 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 {
            return getAllNestedChildrenIncludingParent(parallel, fromTags)
                    .filter(child -> {
                        return child.getAttributes() != null;
                    }).map(child -> {
                        return child.getAttributes();
                    }).flatMap(attributes -> attributes.stream()).filter(filter)
                    .collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
public static Collection<AbstractAttribute> findAttributesByAttributeFilter(
            final boolean parallel,
            final Predicate<? super AbstractAttribute> filter,
            final AbstractHtml... fromTags) throws NullValueException {

        if (filter == null) {
            throw new NullValueException("The tagName 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 {
            return getAllNestedChildrenIncludingParent(parallel, fromTags)
                    .filter(child -> {
                        return child.getAttributes() != null;
                    }).map(child -> {
                        return child.getAttributes();
                    }).flatMap(attributes -> attributes.stream()).filter(filter)
                    .collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
Finds and returns the collection of attributes (including from nested
tags) of the tags by the given filter.

@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 filter
the filter lambda expression containing return true
to include and false to exclude.
@param fromTags
from which the findings to be done.
@return the collection of attributes of the tags by the given filter.
@throws NullValueException
if the {@code filter} or {@code fromTags}
is null
@since 3.0.0
@author WFF