wffweb/src/main/java/com/webfirmframework/wffweb/tag/repository/TagRepository.java
@SuppressWarnings("unchecked")
    public static <T extends AbstractHtml> Collection<T> findTagsAssignableToTag(
            final boolean parallel, final Class<T> tagClass,
            final AbstractHtml... fromTags)
            throws NullValueException, InvalidTagException {

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

        if (NoTag.class.isAssignableFrom(tagClass)) {
            throw new InvalidTagException(
                    "classes like NoTag.class cannot be used to find tags as it's not a logical tag in behaviour.");
        }

        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 (Collection<T>) getAllNestedChildrenIncludingParent(parallel,
                    fromTags).filter(tag -> {
                        return tagClass.isAssignableFrom(tag.getClass())
                                && !NoTag.class
                                        .isAssignableFrom(tag.getClass());
                    }).collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
@SuppressWarnings("unchecked")
    public static <T extends AbstractHtml> Collection<T> findTagsAssignableToTag(
            final boolean parallel, final Class<T> tagClass,
            final AbstractHtml... fromTags)
            throws NullValueException, InvalidTagException {

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

        if (NoTag.class.isAssignableFrom(tagClass)) {
            throw new InvalidTagException(
                    "classes like NoTag.class cannot be used to find tags as it's not a logical tag in behaviour.");
        }

        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 (Collection<T>) getAllNestedChildrenIncludingParent(parallel,
                    fromTags).filter(tag -> {
                        return tagClass.isAssignableFrom(tag.getClass())
                                && !NoTag.class
                                        .isAssignableFrom(tag.getClass());
                    }).collect(Collectors.toSet());
        } finally {
            for (final Lock lock : locks) {
                lock.unlock();
            }
        }
    }
@ SuppressWarnings ( "unchecked" ) public static < T extends AbstractHtml > Collection < T > findTagsAssignableToTag ( final boolean parallel , final Class < T > tagClass , final AbstractHtml ... fromTags ) throws NullValueException , InvalidTagException { if ( tagClass == null ) { throw new NullValueException ( "The tagClass should not be null" ) ; } if ( NoTag . class . isAssignableFrom ( tagClass ) ) { throw new InvalidTagException ( "classes like NoTag.class cannot be used to find tags as it's not a logical tag in behaviour." ) ; } 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 ( Collection < T > ) getAllNestedChildrenIncludingParent ( parallel , fromTags ) . filter ( tag -> { return tagClass . isAssignableFrom ( tag . getClass ( ) ) && ! NoTag . class . isAssignableFrom ( tag . getClass ( ) ) ; } ) . collect ( Collectors . toSet ( ) ) ; } finally { for ( final Lock lock : locks ) { lock . unlock ( ) ; } } }
Finds and returns the all matching (including from nested tags) tags
(which is assignable to the given tag class). <br>
<br>

<pre>
<code>
Html html = new Html(null) {{
new Head(this) {{
new TitleTag(this){{
new NoTag(this, "some title");
}};
}};
new Body(this, new Id("one")) {{
new Div(this);
new Div(this) {{
new Div(this) {{
new Div(this);
}};
}};
new Div(this);
}};
}};

Collection&lt;Head&gt; heads = TagRepository.findTagsAssignableToTag(Head.class, html);
Collection&lt;Div&gt; divs = TagRepository.findTagsAssignableToTag(Div.class, html);

System.out.println(heads.size());
System.out.println(divs.size());

//prints

1
5

</code>
</pre>

@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 tagClass
the class of the tag.
@param fromTags
from which the findings to be done.
@return the all matching tags which is assignable to the given tag class.
@throws NullValueException
if the {@code tagClass} or
{@code fromTags} is null
@throws InvalidTagException
if the given tag class is NoTag.class
@since 3.0.0
@author WFF
Finds and returns the all matching ( including from nested tags ) tags ( which is assignable to the given tag class ) . <br > <br >