001package Torello.JavaDoc.SyntaxHiLite;
002
003import Torello.HTML.InnerTagKeyException;
004import Torello.CSS.ClassNameCSSException;
005
006import Torello.HTML.HTMLNode;
007import Torello.HTML.TagNode;
008import Torello.HTML.SD;
009import Torello.HTML.HTMLPage;
010import Torello.HTML.Util;
011
012import Torello.Java.FileRW;
013import Torello.Java.UnreachableError;
014
015import Torello.Java.ReadOnly.ReadOnlyMap;
016import Torello.Java.ReadOnly.ROTreeMapBuilder;
017
018import Torello.Java.Additional.Ret2;
019
020import static Torello.Java.C.BYELLOW;
021import static Torello.Java.C.RESET;
022
023import java.util.Vector;
024import java.util.Objects;
025import java.util.Iterator;
026
027import java.io.IOException;
028
029public class HiLiteHTML
030    extends AbstractHiLiter
031    implements java.io.Serializable
032{
033    protected static final long serialVersionUID = 1;
034
035
036    // ********************************************************************************************
037    // ********************************************************************************************
038    // Special Attribute HiLiting: Additional / Extra Configuration Class
039    // ********************************************************************************************
040    // ********************************************************************************************
041
042
043    public static class Indices
044    {
045        private Indices() { }
046
047        public static final byte COMMENTS       = 1;
048        public static final byte OPENING_TAGS   = 2;
049        public static final byte CLOSING_TAGS   = 3;
050
051        public static final byte LT_GT_S        = 4;
052        public static final byte TAG_NAMES      = 5;
053        public static final byte ATTR_KEYS      = 6;
054        public static final byte ATTR_VALS      = 7;
055        public static final byte SPLITS         = 8;
056
057        // any_array.length => 9 (Note that any_array[0] is unused!)
058        public static final byte CONFIG_ARR_LEN = 9;  
059    }
060
061
062    // ********************************************************************************************
063    // ********************************************************************************************
064    // STATIC-INNER-CLASS: Config
065    // ********************************************************************************************
066    // ********************************************************************************************
067
068
069    public static class Config
070        extends AbstractConfig<Torello.JavaDoc.SyntaxHiLite.HiLiteHTML.Config>
071        implements java.io.Serializable, Cloneable
072    {    
073        protected static final long serialVersionUID = 1;
074
075        /*
076        spansOrBolds[0] = who-cares?
077
078        spansOrBolds[Indices.COMMENTS]      = true;
079        spansOrBolds[Indices.OPENING_TAGS]  = true;
080        spansOrBolds[Indices.CLOSING_TAGS]  = true;
081
082        spansOrBolds[Indices.LT_GT_S]       = false;
083        spansOrBolds[Indices.TAG_NAMES]     = false;
084        spansOrBolds[Indices.ATTR_KEYS]     = false;
085        spansOrBolds[Indices.ATTR_VALS]     = false;
086        spansOrBolds[Indices.SPLITS]        = false;
087        */
088
089        private static final boolean[] default_SpansOrBolds = new boolean[]
090        { false, true, true, true, false, false, false, false, false };
091
092        // This is "Package-Private" - it might be used by the equals, tostring and clone methods!
093        ROTreeMapBuilder<String, AttribRule> rotmb = null;
094
095        public Config()
096        { super(Indices.CONFIG_ARR_LEN, default_SpansOrBolds, HiLiteHTML.Config.class); }
097
098        private Config(HiLiteHTML.Config c)
099        {
100            super(c);
101            if (c.rotmb != null) this.rotmb = c.rotmb.clone();
102        }
103
104
105        // ****************************************************************************************
106        // ****************************************************************************************
107        // Class-Config - java.lang.Object & java.lang.Cloneable
108        // ****************************************************************************************
109        // ****************************************************************************************
110
111
112        public boolean equals(Object other)
113        {
114            if (! super.equals(other)) return false;
115            return ((HiLiteHTML.Config) other).rotmb.equals(this.rotmb);
116        }
117
118        public String toString()
119        { return ToStringHTML.classConfig(this); }
120
121        public HiLiteHTML.Config clone()
122        { return new HiLiteHTML.Config(this); }
123
124
125        // ****************************************************************************************
126        // ****************************************************************************************
127        // Class-Config - The Methods added (in addition to) those in super-class "AbstractConfig"
128        // ****************************************************************************************
129        // ****************************************************************************************
130
131
132        public synchronized HiLiteHTML.Config addRule(AttribRule rule)
133        {
134            AttribRule ar = rule.clone();
135            ar.validate();
136            if (this.rotmb == null) this.rotmb = new ROTreeMapBuilder<>();
137            rotmb.put(rule.attributeName, rule);
138            return this;
139        }
140
141        public synchronized Iterator<AttribRule> getExtraAttribRules()
142        {
143            return (this.rotmb == null)
144                ? java.util.Collections.emptyIterator()
145                : rotmb.values().iterator();
146        }
147
148
149        // ****************************************************************************************
150        // ****************************************************************************************
151        // STATIC-INNER-CLASS Config: Generate HiLiteHTML
152        // ****************************************************************************************
153        // ****************************************************************************************
154
155
156        public synchronized HiLiteHTML generateHiLiter() 
157        {
158            Ret2<TagNode[], TagNode[]> r2 = generateHiLiterHelper();
159
160            final ReadOnlyMap<String, AttribRule> rom = (this.rotmb != null)
161                ? this.rotmb.build()
162                : null;
163
164            return new HiLiteHTML(r2.a /* openers */, r2.b /* closers */, this.utilize, rom);
165        }
166    }
167
168
169    // ********************************************************************************************
170    // ********************************************************************************************
171    // Special Attribute HiLiting: Additional / Extra Configuration Class
172    // ********************************************************************************************
173    // ********************************************************************************************
174
175
176    public static class AttribRule implements java.io.Serializable, Cloneable
177    {
178        protected static final long serialVersionUID = 1;
179
180        public String attributeName             = null;
181        public String attributeName_ClassName   = null;
182        public String attributeValue_ClassName  = null;
183
184        public boolean spanOrBold = true;
185
186        public AttribRule() { }
187
188        public void validate()
189        {
190            InnerTagKeyException.check(this.attributeName);
191            ClassNameCSSException.check(this.attributeName_ClassName);
192            ClassNameCSSException.check(this.attributeValue_ClassName);
193        }
194
195        public HiLiteHTML.AttribRule clone()
196        {
197            final HiLiteHTML.AttribRule ret = new HiLiteHTML.AttribRule();
198    
199            ret.attributeName               = this.attributeName;
200            ret.attributeName_ClassName     = this.attributeName_ClassName;
201            ret.attributeValue_ClassName    = this.attributeValue_ClassName;
202            ret.spanOrBold                  = this.spanOrBold;
203    
204            return ret;
205        }
206    
207        public boolean equals(Object other)
208        {
209            if (! (other instanceof HiLiteHTML.AttribRule)) return false;
210    
211            HiLiteHTML.AttribRule o = (HiLiteHTML.AttribRule) other;
212    
213            return
214                    Objects.equals(this.attributeName, o.attributeName)
215                &&  Objects.equals(this.attributeName_ClassName, o.attributeName_ClassName)
216                &&  Objects.equals(this.attributeValue_ClassName, o.attributeValue_ClassName)
217                &&  (this.spanOrBold == o.spanOrBold);
218        }
219
220        public String toString()
221        { return ToStringHTML.classAttribRule(this); }
222
223        public int hashCode()
224        { return this.attributeName.hashCode(); }
225
226    }
227
228
229    // ********************************************************************************************
230    // ********************************************************************************************
231    // MAIN-CLASS
232    // ********************************************************************************************
233    // ********************************************************************************************
234
235
236    private final DoHiLiteHTML.TagsNonPWA tags;
237    private final DoHiLiteHTML.TagsPWA tpwa;
238
239    public final ReadOnlyMap<String, AttribRule> extraRules;
240
241    private HiLiteHTML(
242            final TagNode[] openers,
243            final TagNode[] closers,
244            final boolean[] utilize,
245            final ReadOnlyMap<String, AttribRule> extraRules
246        )
247    {
248        super(openers, closers, utilize);
249
250        this.tags       = new DoHiLiteHTML.TagsNonPWA(openers, closers, utilize);
251        this.tpwa       = new DoHiLiteHTML.TagsPWA(openers, closers, utilize);
252        this.extraRules = extraRules;
253    }
254
255    public static HiLiteHTML generateHiLiterDefault()
256    { return new Config().generateHiLiter(); }
257
258    public Vector<HTMLNode> hiLite(Vector<HTMLNode> html)
259    { return DoHiLiteHTML.run(html, this.tpwa, this.tags); }
260
261    public String toString()
262    { return ToStringHTML.classHiLiteHTML(this, this.CONFIG_ARR_LEN, this.tags, this.tpwa); }
263
264    public boolean equals(Object other)
265    {
266        return (! super.equals(other))
267            ? false
268            : this.extraRules.equals(((HiLiteHTML) other).extraRules);
269    }
270
271
272    // ********************************************************************************************
273    // ********************************************************************************************
274    // Testing This
275    // ********************************************************************************************
276    // ********************************************************************************************
277
278
279    public static void main(String[] argv) throws IOException 
280    {
281        String htmlAsStr =
282            FileRW.loadFileToString("Torello/BuildJAR/Documentation/Global/Appendable.html");
283
284        Vector<HTMLNode> htmlAsVec = HTMLPage.getPageTokens(htmlAsStr, false);
285
286        HiLiteHTML hl = new Config().generateHiLiter();
287
288        final String css = FileRW.loadFileToString
289            ("Torello/HTML/Tools/SyntaxHiLite/data-files/html-default.css");
290
291        String hiLitedHTML = 
292            "<HTML>\n<HEAD>\n" +
293            "<META HTTP-EQUIV=Cache-Control CONTENT='no-cache, no-store, must-revalidate'>\n" +
294            "<META HTTP-EQUIV=Pragma CONTENT=no-cache>\n" +
295            "<META HTTP-EQUIV=Expires CONTENT=0>\n" +
296            "<STYLE TYPE='text/css'>\n" +
297            css + '\n' +
298            "</STYLE>\n" +
299            "</HEAD>\n" +
300            "<BODY>\n" +
301            "<PRE CLASS=HL>\n" +
302            Util.pageToString(hl.hiLite(htmlAsVec)) + '\n' +
303            "</PRE>\n" +
304            "</BODY>\n"  +
305            "</HTML>\n";
306
307        System.out.println("Writing File: " + BYELLOW + "OUT/out.html" + RESET);
308        FileRW.writeFile(hiLitedHTML, "OUT/out.html");
309
310        System.out.println(hl.toString());
311    }
312}