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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package Torello.HTML;

import static Torello.HTML.Attributes.Filter;

import Torello.Java.LV;

import java.util.Vector;
import java.util.List;
import java.util.Properties;

import java.util.stream.IntStream;
import java.util.stream.Collectors;

class UpdateWithFilter
{
    static int[] update(
            final Vector<? super TagNode>   html,
            final int                       sPos,
            final int                       ePos,
            final Filter                    f
        )
    {
        // Save Modified node-locations in a java stream (Use the "Primitive Int Stream")
        IntStream.Builder b = IntStream.builder();

        // Temp-Loop Variables
        LV          l   = new LV(sPos, ePos, html);
        Properties  p;
        TagNode     tn;

        for (int i=l.start; i < l.end; i++)

            if (
                // Only Opening TagNode's that could possibly have attributes.
                ((tn = ((HTMLNode) html.elementAt(i)).openTagPWA()) != null)

                // Retrieve all Attribute Key-Value Pairs.  Take note of surrounding quotes.
                &&  ((p = tn.allAV(true, true)).size() > 0)

                // Run the provided filter logic, if it returns TRUE, then build new TagNode
                &&  f.filter(tn.tok, p)
            )
            {
                // This makes sure not to leave out any possible "boolean" (a.k.a "Key Only") 
                // attributes when we rebuild the new TagNode.  An example of a "boolean" attribute
                // in HTML is "HIDDEN" which is a key that does not require any value to convey its
                // purpose or function.  Sometimes web-page designers might type "HIDDENT=TRUE",
                // but it is not necessary.  In any case, the "allAV(boolean, boolean)" method only
                // returns attributes that have BOTH a 'key' AND a 'value'.

                List<String> keyOnly = tn.allKeyOnlyAttributes(true).collect(Collectors.toList());

                // Build a new TagNode, then replace the old one
                tn = new TagNode(tn.tok, p, keyOnly, null, tn.str.endsWith("/>")); 
                html.setElementAt(tn, i);


                // Save the vector-index where a replacement has occurred.  The user will be
                // provided a list of all locations where an old TagNode was replaced with a new one.

                b.accept(i);
            }

        // Build the IntStream, Convert the IntStream -> int[], Return it.
        return b.build().toArray(); 
    }

    static int[] update(
            final Vector<? super TagNode>   html,
            final int[]                     posArr,
            final Filter                    f
        )
    {
        // Use Java Stream to keep a list of Vector-Locations that were updated / modified.
        IntStream.Builder b = IntStream.builder();

        for (int i: posArr)
        {
            HTMLNode n = (HTMLNode) html.elementAt(i);

            if (! n.isTagNode()) throw new TagNodeExpectedException(i);

            TagNode tn = (TagNode) n;

            if (tn.isClosing) throw new OpeningTagNodeExpectedException(i);


            // If element-length < tok-length+5, there are no attributes!
            // '<', TOKEN, SPACE, ATTRIBUTE<MIN-1>, '=', '>'

            if (tn.str.length() < (tn.tok.length() + 5)) continue;

            // Retrieve all Attribute Key-Value Pairs.
            Properties p =  tn.allAV(true, true);


            // This makes sure not to leave out any possible "boolean" (a.k.a "Key Only") 
            // attributes when we rebuild the new TagNode.   An example of a "boolean" attribute
            // in HTML is "HIDDEN" which is a key that does not require any value to convey its
            // purpose or function.  Sometimes web-page designers might type "HIDDENT=TRUE", but
            // it is not necessary.  In any case, the "allAV(boolean, boolean)" method only returns
            // attributes that have BOTH a 'key' AND a 'value'.

            List<String> keyOnly = tn.allKeyOnlyAttributes(true).collect(Collectors.toList());

            // Run the provided filter logic, if it returns TRUE, then build new TagNode
            if ((p.size() > 0) && f.filter(tn.tok, p))
            {
                // Build a new TagNode, and replace the old one.
                tn = new TagNode(tn.tok, p, keyOnly, null, tn.str.endsWith("/>"));
                html.setElementAt(tn, i);


                // Save the vector-index where a replacement has occured.  The user will be
                // provided a list of all locations where an old TagNode was replaced with a
                // new one.

                b.accept(i);
            }
        }

        // Build the IntStream, Convert the IntStream -> int[], Return it.
        return b.build().toArray();
    }

}