1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package Torello.HTML.NodeSearch;

import java.util.*;
import java.util.regex.Pattern;
import java.util.function.Predicate;

import Torello.HTML.*;
import Torello.Java.LV;

/**
 * {@code Static} methods for building and instantiating an
 * {@link HNLI}<CODE>&lt;</CODE>{@link TagNode}<CODE>&gt;</CODE> (which extends the basic
 * iterator class) for iterating the tags inside of an HTML-{@code Vector}, using match-critera
 * which specify attribute name &amp; value requirements.
 * 
 * <BR /><BR /><EMBED CLASS='external-html' DATA-FILE-ID=InnerTagIterator> 
 */
@Torello.JavaDoc.JDHeaderBackgroundImg
@Torello.JavaDoc.StaticFunctional
public class InnerTagIterator
{
    private InnerTagIterator() { }

    // **** CRITERIA: htmlTag
    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String htmlTag, String innerTag)
    { return GET(html, ARGCHECK.htmlTag(htmlTag), ARGCHECK.innerTag(innerTag), ARGCHECK.TRUE); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String htmlTag, String innerTag, TextComparitor tc, String... compareStr)
    { return GET(html, ARGCHECK.htmlTag(htmlTag), ARGCHECK.innerTag(innerTag), ARGCHECK.TC(tc, compareStr)); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String htmlTag, String innerTag, Pattern p)
    { return GET(html, ARGCHECK.htmlTag(htmlTag), ARGCHECK.innerTag(innerTag), ARGCHECK.REGEX(p)); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String htmlTag, String innerTag, Predicate<String> attributeValuePred)
    { return GET(html, ARGCHECK.htmlTag(htmlTag), ARGCHECK.innerTag(innerTag), attributeValuePred); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, Predicate<TagNode> p, String... htmlTags)
    { return GET(html, p, ARGCHECK.htmlTags(htmlTags)); }

    // **** CRITERIA, htmlTag null
    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String innerTag)
    { return GET(html, null, ARGCHECK.innerTag(innerTag), ARGCHECK.TRUE); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String innerTag, TextComparitor tc, String... compareStr)
    { return GET(html, null, ARGCHECK.innerTag(innerTag), ARGCHECK.TC(tc, compareStr)); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String innerTag, Pattern p)
    { return GET(html, null, ARGCHECK.innerTag(innerTag), ARGCHECK.REGEX(p)); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, String innerTag, Predicate<String> attributeValuePred)
    { return GET(html, null, ARGCHECK.innerTag(innerTag), attributeValuePred); }

    public static HNLI<TagNode> get(Vector<? extends HTMLNode> html, Predicate<TagNode> p)
    { return GET(html, p); }

    // ******************************************************************************
    // private builder methods
    // ******************************************************************************

    private static HNLI<TagNode> GET
        (Vector<? extends HTMLNode> html, Predicate<TagNode> p, String... htmlTags)
    {
        Predicate<TagNode>  p2 = (htmlTags.length == 0)
                ? (TagNode tn) -> (! tn.isClosing) && p.test(tn)
                : (TagNode tn) -> (! tn.isClosing) && tn.isTag(htmlTags) && p.test(tn);
    
        return new HNLI<TagNode>(html, p2, TagNode.class);
    }

    private static HNLI<TagNode> GET
        (Vector<? extends HTMLNode> html, String htmlTag, String innerTag, Predicate<String> compare)
    {
        if (htmlTag == null) return new HNLI<TagNode>(html,
            tagNode ->
            {
                if (tagNode.isClosing) return false;

                String innerTagValue = tagNode.AVOPT(innerTag);

                return (innerTagValue != null) && compare.test(innerTagValue);

            }, TagNode.class
                // The HNLI expects the last parameter to its constructor to be the class of the
                // iterator.  This is the solution to the "Java Generics Type Erasure Problem"
        );

        else return new HNLI<TagNode>(html,
            tagNode ->
            {
                if (tagNode.isClosing) return false;

                if (! htmlTag.equals(tagNode.tok)) return false;

                String innerTagValue = tagNode.AVOPT(innerTag);

                return (innerTagValue != null) && compare.test(innerTagValue);

            }, TagNode.class
                // REMEMBER, the HNLI<...> Generic class will iterate through
                // TagNode's, TextNode's and CommentNode's.  The only one of these
                // three that may be more difficult is the "TagNode" class - because it has
                // both opening and closing versions of the node, and more data-fields.  The
                // TextNode and CommentNode classes do not have "extra" data-fields that contain
                // more information, nor are there "different types" of TextNode's and CommentNode's
                // The HNLI expects the last parameter to its constructor to be the class of the
                // iterator. This is the solution to the "Java Generics Type Erasure Problem"
        );
    }

}