001package Torello.HTML;
002
003import Torello.Java.*;
004import java.util.*;
005
006/**
007 * <CODE>AUM (Attribute Update Mode) - Documentation.</CODE><BR /><BR />
008 * <EMBED CLASS='external-html' DATA-FILE-ID=AUM>
009 *
010 * @see Attributes#update(Vector, AUM, String, String, SD)
011 * @see Attributes#update(Vector, AUM, int, int, String, String, SD)
012 * @see Attributes#update(Vector, AUM, int[], String, String, SD)
013 */
014public enum AUM
015{
016    /**
017     * {@code Set}, when used as an Attribute Update Method, tells the HTML Element Attribute
018     * Update Logic to either <B>1)</B> replace the current
019     * attribute-<B STYLE="color: red;">value</B> with the new text-{@code String}, or <B>2)</B> If
020     * there is no attribute <B STYLE="color: red;">key-value</B> with the provided inner-tag
021     * <B STYLE="color: red;">name</B>, then to create a new attribute for the HTML Element for the
022     * provided attribute-<B STYLE="color: red;">key</B> and <B STYLE="color: red;">value</B> and
023     * insert this attribute <B STYLE="color: red;">key-value</B> pair into the element.
024     *
025     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
026     * 
027     * <DIV CLASS=SNIP>{@code
028     * // String cur = tn.AV(innerTag);
029     * case Set: return tn.setAV(innerTag, innerTagValue, quote);
030     * }</DIV>
031     *
032     * <DIV CLASS=EXAMPLE>{@code
033     * // Example 1
034     * String   innerTag        = "target";
035     * String   innerTagValue   = "_BLANK";
036     * AUM      mode            = AUM.Set;
037     * TagNode  tn              = new TagNode("<A HREF='nextIndex.html'>");
038     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
039     * // newTN.str             ==> <A HREF='nextIndex.html' target='_BLANK'>
040     *                          // New 'target' attribute key-value pair inserted into HTML Element
041     *
042     * // Example 2
043     * String   innerTag        = "target";
044     * String   innerTagValue   = "_BLANK";
045     * AUM      mode            = AUM.Set;
046     * TagNode  tn              = new TagNode("<A HREF='nextIndex.html' TARGET='_Self'>");
047     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
048     * // newTN.str             ==> <A HREF='nextIndex.html' target='_BLANK'>
049     *                          // Old 'target' attribute key-value pair is replaced with new value
050     * }</DIV>
051     * 
052     * @see #update(TagNode, String, String, SD)
053     * @see HTMLNode#str
054     */
055    Set,
056
057    /**
058     * {@code Replace} when used as an Attribute Update Method, tells the HTML Element Attribute
059     * Update Logic to <I><B>replace</I></B> any attribute <B STYLE="color: red;">key-value</B>
060     * pair that the Element contains; <B><I>however</I></B> if there is no current 
061     * <B STYLE="color: red;">key-value</B> pair that has the provided attribute
062     * <B STYLE="color: red;">name</B>, then the HTML Element Node should be skipped, and left
063     * un-modified.
064     *
065     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
066     * 
067     * <DIV CLASS=SNIP>{@code
068     * // String cur = tn.AV(innerTag);
069     * case Replace: return (cur != null)
070     *     ? tn.setAV(innerTag, innerTagValue, quote)
071     *     : return null;
072     * }</DIV>
073     *
074     * <DIV CLASS=EXAMPLE>{@code
075     * // Example 1
076     * String   innerTag        = "style";
077     * String   innerTagValue   = "color: red;";
078     * AUM      mode            = AUM.Replace;
079     * TagNode  tn              = new TagNode("<A HREF='nextIndex.html' STYLE='font-weight: bold;'>");
080     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
081     * // newTN.str             ==> <A HREF='nextIndex.html' style='color: red;'>
082     *                          // Old 'style' attribute key-value pair is replaced with new value  
083     *
084     * // Example 2
085     * String   innerTag        = "style";
086     * String   innerTagValue   = "color: red;";
087     * AUM      mode            = AUM.Replace;
088     * TagNode  tn              = new TagNode("<A HREF='nextIndex.html'>");
089     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
090     * // newTN                 ==> null
091     *                          // NOTE: HTML Element left unchanged, because it did not actually
092     *                          //       have a 'style' attribute in the first place. 
093     *                          //       A return value of 'null' implies this AUM does not result
094     *                          //       in a replacement or update for the TagNode passed.
095     * }</DIV>
096     * 
097     * @see #update(TagNode, String, String, SD)
098     * @see HTMLNode#str
099     */ 
100    Replace,
101 
102    /**
103     * {@code RemoveSubString} when used as an Attribute Update Method, tells the HTML Element
104     * Attribute Update Logic to <I><B>remove</I></B> the first copy found of a provided sub-string
105     * from the attribute-<B STYLE="color: red;">value</B> whose attribute
106     * <B STYLE="color: red;">name</B> matches the provided inner-tag
107     * <B STYLE="color: red;">name</B>.
108     *
109     * <BR /><BR /><DIV CLASS=JDHoveringDesc>
110     * <B>For Instance:</B> If AUM.RemoveSubString were used with an HTML Element
111     * that looked like: <SPAN STYLE="color: lightbrown; font-weight: bold;">
112     * <BR />{@code <DIV CLASS='MyClass MyPage Corporation123'>}</SPAN>
113     * 
114     * <BR /><BR />
115     * <B>Where:</B> {@code innerTag = "CLASS"} and {@code innerTagValue = "Corporation123"}
116     * 
117     * <BR /><BR /><B>Then:</B> The HTML Element would be updated to:
118     * <SPAN STYLE="color: blue; font-weight: bold;">
119     * <BR />{@code <DIV CLASS='MyClass MyPage '>}
120     * </SPAN>
121     * 
122     * <BR /><BR /><B>NOTE:</B> This uses Java's {@code String.indexOf(...)} method, and will only
123     * remove the first-instance of the substring.
124     * 
125     * <BR /><BR /><B>ALSO:</B> There is a remaining 'extra-space' that was not removed along with
126     * the {@code 'corporation123'} String.  Keep in mind white-space when using java to modify text.
127     * </DIV>
128     *
129     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
130     * 
131     * <DIV CLASS="SNIP">{@code
132     * // String cur = tn.AV(innerTag);
133     * case RemoveSubString: return ((cur != null) && (cur.indexOf(innerTagValue) != -1))
134     *     ? tn.setAV(innerTag, cur.replace(innerTagValue, ""), quote)
135     *     : null;
136     * }</DIV>
137     * 
138     * @see #update(TagNode, String, String, SD)
139     * @see HTMLNode#str
140     */
141    RemoveSubString,
142
143    /**
144     * This performs the exact same routine as {@code AUM.RemoveSubstring}, however the
145     * text-{@code String} comparison ignores case for the alphabetic letters a..z.  This HTML
146     * Element Update Routine, just like the {@code AUM.RemoveSubstring}, also only removes the
147     * first instance found of the provided substring.
148     *
149     * <BR /><BR /><DIV CLASS=JDHoveringDesc>
150     * <B>For Instance:</B> If AUM.RemoveSubString_CI were used with an HTML Element
151     * that looked like: <SPAN STYLE="color: lightbrown; font-weight: bold;">
152     * <BR />{@code <DIV CLASS='MyClass MyPage Corporation123' STYLE='FONT-WEIGHT: BOLD; COLOR:
153     * RED;'>}</SPAN>
154     * 
155     * <BR /><BR />
156     * <B>Where:</B> {@code innerTag = "STYLE"} and {@code innerTagValue = "color: red;"}
157     * 
158     * <BR /><BR /><B>Then:</B> The HTML Element would be updated to:
159     * <SPAN STYLE="color: blue; font-weight: bold;">
160     * <BR />{@code <DIV CLASS='MyClass MyPage Corporation123'STYLE='FONT-WEIGHT: BOLD; '>}</SPAN>
161     * 
162     * <BR /><BR /><B>NOTE:</B> This uses java's {@code StrCmpr.indexOfIgnoreCase(...)} method, and
163     * will only remove the first-instance of the substring (ignoring case).  In the original HTML
164     * Element, the words 'COLOR' and 'RED' were capitalized.  Using this 'Case-Insensitive'
165     * removal, the user can catch any version.  This, fortunately, is how CSS 'Style' Attributes
166     * work!
167     * 
168     * <BR /><BR /><B>ALSO:</B> There is a remaining 'extra-space' that was not removed along with
169     * the 'corporation123' string.  Keep in mind white-space when using java to modify text.
170     * </DIV>
171     *
172     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
173     * 
174     * <DIV CLASS=SNIP>{@code
175     * // String cur = tn.AV(innerTag);
176     * case RemoveSubString_CI:
177     *          int i;
178     *          return ((cur != null) && ((i = StrIndexOf.first_CI(cur, innerTagValue)) != -1))
179     *
180     *              ? (tn.setAV(innerTag, cur.substring(0, i) + 
181     *                cur.substring(i + innerTagValue.length()), quote))
182     *
183     *              : null;
184     * }</DIV>
185     * 
186     * @see #update(TagNode, String, String, SD)
187     * @see HTMLNode#str
188     */
189    RemoveSubString_CI,
190
191    /**
192     * {@code ConcatToStart} when used as an Attribute Update Method, tells the HTML Element
193     * Attribute Update Logic to <I><B>concatenate</I></B> the provided
194     * attribute-<B STYLE="color: red;">value</B> to <I><B>an already in place</B></I>
195     * attribute-<B STYLE="color: red;">value</B> before the beginning of the current
196     * attribute-<B STYLE="color: red;">value</B> {@code String}. <B><I>However</I></B> if there is
197     * no current <B STYLE="color: red;">key-value</B> pair that has the provided attribute
198     * <B STYLE="color: red;">name</B>, then the HTML Element Node should be skipped, and left
199     * un-modified.
200     *
201     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
202     * 
203     * <DIV CLASS=SNIP>{@code
204     * // String cur = tn.AV(innerTag);
205     * case ConcatToStart: return (cur != null) 
206     *     ? tn.setAV(innerTag, innerTagValue + cur, quote)
207     *     : null;
208     * }</DIV>
209     *
210     * <BR /><DIV CLASS=EXAMPLE>{@code
211     * // Example 1
212     * String   innerTag        = "id";
213     * String   innerTagValue   = "JAVA-AUM-";
214     * AUM      mode            = AUM.ConcatToStart;
215     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ID='MyPage'>");
216     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
217     * // newTN.str             ==> <IMG SRC='img-123.jpg' id='JAVA-AUM-MyPage'>
218     *
219     * // Example 2
220     * String   innerTag        = "id";
221     * String   innerTagValue   = "JAVA-AUM-";
222     * AUM      mode            = AUM.ConcatToStart;
223     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
224     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
225     * // newTN                 ==> null
226     *                          // NOTE: HTML Element left unchanged, because it did not actually
227     *                          //       have an 'id' attribute in the first place. 
228     *                          //       A return value of 'null' implies this AUM does not result
229     *                          //       in a replacement or update for the TagNode passed.
230     * }</DIV>
231     * 
232     * @see #update(TagNode, String, String, SD)
233     * @see HTMLNode#str
234     */
235    ConcatToStart,
236
237    /**
238     * {@code ConcatToStart} when used as an Attribute Update Method, tells the HTML Element
239     * Attribute Update Logic to <I><B>concatenate</I></B> the provided
240     * attribute-<B STYLE="color: red;">value</B> to <I><B>an already in place</B></I>
241     * attribute-<B STYLE="color: red;">value</B> before the beginning of the current
242     * attribute-<B STYLE="color: red;">value</B> {@code String}. If there is no current
243     * <B STYLE="color: red;">key-value</B> pair that has the provided attribute
244     * <B STYLE="color: red;">name</B>, a new Inner-Tag <B STYLE="color: red;">key-value</B> pair
245     * should be added to the HTML Element Node using the provided
246     * <B STYLE="color: red;">key</B>-{@code String} and
247     * <B STYLE="color: red;">value</B>-{@code String}.
248     *
249     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
250     * 
251     * <DIV CLASS=SNIP>{@code
252     * // String cur = tn.AV(innerTag);
253     * case ConcatToStartOrSet: return (cur != null) 
254     *     ? tn.setAV(innerTag, innerTagValue + cur, quote)
255     *     : tn.setAV(innerTag, innerTagValue, quote);
256     * }</DIV>
257     *
258     * <DIV CLASS=EXAMPLE>{@code
259     * // Example 1
260     * String   innerTag        = "alt";
261     * String   innerTagValue   = "This is a personal photo.";
262     * AUM      mode            = AUM.ConcatToStartOrSet;
263     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
264     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
265     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a personal photo.'>  
266     *                          // The original TagNode did not have an 'alt' Inner-Tag, but
267     *                          // because this AUM has the "OrSet" requirement, when a TagNode
268     *                          // that's lacking the requested Inner-Tag, the AUM.update method
269     *                          // will not return null, but instead create a new attribute
270     *                          // key-value pair, and set the value to the requested parameter.
271     *
272     * // Example 2
273     * String   innerTag        = "alt";
274     * String   innerTagValue   = "This is a personal photo.";
275     * AUM      mode            = AUM.ConcatToStartOrSet;
276     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ALT='Bob Wilson'>");
277     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
278     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a personal photo.Bob Wilson'> 
279     *                          // NOTE: There is no space between the period, and the beginning of the
280     *                          //       next sentence in the ALT Inner-Tag above! 
281     * }</DIV>
282     * 
283     * @see #update(TagNode, String, String, SD)
284     * @see Torello.HTML.HTMLNode#str
285     */
286    ConcatToStartOrSet,
287
288    /**
289     * This {@code AUM} enumerated type is precisely identical to the one named
290     * {@code ConcatToStart} - <I><B>except</B></I> that in the case where the inner-tag
291     * <B STYLE="color: red;">value</B> is appended, a space is added immediately after the newly
292     * added {@code String}-<B STYLE="color: red;">value</B> token. 
293     * 
294     * <BR /><BR /><DIV CLASS=JDHint>
295     * The primary reason for adding this surprisingly subtle and minor difference is to remind
296     * users that keeping up with spaces when tweaking HTML inner-tags can be a bug source.
297     * </DIV>
298     * 
299     * <BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
300     * 
301     * <DIV CLASS=SNIP>{@code
302     * // String cur = tn.AV(innerTag);
303     * case ConcatToStartAddSpace: return (cur != null) 
304     *     ? tn.setAV(innerTag, innerTagValue + ' ' + cur, quote)
305     *     : null;
306     * }</DIV>
307     *
308     * <DIV CLASS=EXAMPLE>{@code
309     * // Example 1
310     * String   innerTag        = "id";
311     * String   innerTagValue   = "JAVA-AUM";
312     * AUM      mode            = AUM.ConcatToStartAddSpace;
313     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ID='MyPage'>");
314     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
315     * // newTN.str             ==> <IMG SRC='img-123.jpg' id='JAVA-AUM MyPage'>
316     *
317     * // Example 2
318     * String   innerTag        = "id";
319     * String   innerTagValue   = "JAVA-AUM";
320     * AUM      mode            = AUM.ConcatToStartAddSpace;
321     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
322     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
323     * // newTN                 ==> null
324     *                          // NOTE: HTML Element left unchanged, because it did not actually
325     *                          //       have an 'id' attribute in the first place. 
326     *                          //       A return value of 'null' implies this AUM does not result
327     *                          //       in a replacement or update for the TagNode passed.
328     * }</DIV>
329     * 
330     * @see #update(TagNode, String, String, SD)
331     * @see Torello.HTML.HTMLNode#str
332     */
333    ConcatToStartAddSpace,
334
335    /**
336     * This {@code AUM} enumerated type is precisely identical to the one named
337     * {@code ConcatToStartOrSet} - <I><B>except</B></I> that in the case where the inner-tag
338     * <B STYLE="color: red;">value</B> is appended (concatenated), a space is added immediately
339     * after the newly added {@code String}-<B STYLE="color: red;">value</B> token.
340     *
341     * <BR /><BR /><DIV CLASS=JDHint>
342     * If there were no inner-tag <B STYLE="color: red;">key-value</B>
343     * pair, and a new one was added - then an extra space would, hopefully this is obvious,
344     * <B>then an extra space would not be needed</B>, and therefore it is not added.
345     * </DIV>
346     *
347     * <BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
348     * 
349     * <DIV CLASS=SNIP>{@code
350     * // String cur = tn.AV(innerTag);
351     * case ConcatToStartOrSetAddSpace: return (cur != null) 
352     *     ? tn.setAV(innerTag, innerTagValue + ' ' + cur, quote)
353     *     : tn.setAV(innerTag, innerTagValue, quote);
354     * }</DIV>
355     *
356     * <DIV CLASS=EXAMPLE>{@code
357     * // Example 1
358     * String   innerTag        = "alt";
359     * String   innerTagValue   = "This is a personal photo.";
360     * AUM      mode            = AUM.ConcatToStartOrSetAddSpace;
361     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ALT='Company XYZ'>");
362     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
363     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a personal photo. Company XYZ'>  
364     *
365     * // Example 2
366     * String   innerTag        = "alt";
367     * String   innerTagValue   = "This is a personal photo.";
368     * AUM      mode            = AUM.ConcatToStartOrSetAddSpace;
369     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
370     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
371     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a personal photo.'>  
372     * }</DIV>
373     * 
374     * @see #update(TagNode, String, String, SD)
375     * @see Torello.HTML.HTMLNode#str
376     */
377    ConcatToStartOrSetAddSpace,
378
379    /**
380     * {@code ConcatToEnd} when used as an Attribute Update Method, tells the HTML Element
381     * Attribute Update Logic to <I><B>concatenate</I></B> the provided
382     * attribute-<B STYLE="color: red;">value</B> to <I><B>an already in place</B></I>
383     * attribute-<B STYLE="color: red;">value</B> at the end of the current
384     * attribute-<B STYLE="color: red;">value</B> {@code String}.  <B><I>However</I></B> if there
385     * is no current <B STYLE="color: red;">key-value</B> pair that has the provided attribute
386     * <B STYLE="color: red;">name</B>, then the HTML Element Node should be skipped, and left
387     * un-modified.
388     *
389     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
390     * 
391     * <DIV CLASS=SNIP>{@code
392     * // String cur = tn.AV(innerTag);
393     * case ConcatToEnd: return (cur != null) 
394     *     ? tn.setAV(innerTag, cur + innerTagValue, quote)
395     *     : null;
396     * }</DIV>
397     *
398     * <DIV CLASS=EXAMPLE>{@code
399     * // Example 1
400     * String   innerTag        = "alt";
401     * String   innerTagValue   = "Photo of Friends";
402     * AUM      mode            = AUM.ConcatToEnd;
403     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ID='MyPage'>");
404     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
405     * // newTN                 ==> null
406     *                          // NOTE: HTML Element left unchanged, because it did not actually
407     *                          //       have an 'alt' attribute in the first place. 
408     *                          //       A return value of 'null' implies this AUM does not result
409     *                          //       in a replacement or update for the TagNode passed.
410     *
411     * // Example 2
412     * String   innerTag        = "alt";
413     * String   innerTagValue   = " - Photo of Friends";
414     * AUM      mode            = AUM.ConcatToEnd;
415     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ALT='Bob Wilson'>");
416     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
417     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='Bob Wilson - Photo of Friends'> 
418     * }</DIV>
419     * 
420     * @see #update(TagNode, String, String, SD)
421     * @see Torello.HTML.HTMLNode#str
422     */
423    ConcatToEnd,
424
425    /**
426     * {@code ConcatToEnd} when used as an Attribute Update Method, tells the HTML Element
427     * Attribute Update Logic to <I><B>concatenate</I></B> the provided
428     * attribute-<B STYLE="color: red;">value</B> to <I><B>an already in place</B></I>
429     * attribute-<B STYLE="color: red;">value</B> at the end of the current
430     * attribute-<B STYLE="color: red;">value</B> {@code String}.  If there is no current
431     * <B STYLE="color: red;">key-value</B> pair that has the provided attribute
432     * <B STYLE="color: red;">name</B>, a new Inner-Tag <B STYLE="color: red;">key-value</B> pair
433     * should be added to the HTML Element Node using the provided
434     * <B STYLE="color: red;">key</B>-{@code String} and
435     * <B STYLE="color: red;">value</B>-{@code String}.
436     *
437     * <BR /><BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
438     * 
439     * <DIV CLASS=SNIP>{@code
440     * // String cur = tn.AV(innerTag);
441     * case ConcatToEndOrSet: return (cur != null) 
442     *     ? tn.setAV(innerTag, cur + innerTagValue, quote)
443     *     : tn.setAV(innerTag, innerTagValue, quote);
444     * }</DIV>
445     *
446     * <DIV CLASS=EXAMPLE>{@code
447     * // Example 1
448     * String   innerTag        = "alt";
449     * String   innerTagValue   = " - This is a personal photo.";
450     * AUM      mode            = AUM.ConcatToEndOrSet;
451     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ALT='Larry'>");
452     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
453     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='Larry - This is a personal photo.'>
454     *                          // NOTE: There is no space between the period, and the beginning of
455     *                          //       the next sentence in the ALT Inner-Tag above!  
456     *
457     * // Example 2
458     * String   innerTag        = "alt";
459     * String   innerTagValue   = "This is a personal photo.";
460     * AUM      mode            = AUM.ConcatToEndOrSet;
461     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
462     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
463     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a personal photo.'>
464     *                          // The original TagNode did not have an 'alt' Inner-Tag, but
465     *                          // because this AUM has the "OrSet" requirement, when a TagNode
466     *                          // that's lacking the requested Inner-Tag, the AUM.update method
467     *                          // will not return null, but instead create a new attribute
468     *                          // key-value pair, and set the value to the requested parameter.
469     * }</DIV>
470     * 
471     * @see #update(TagNode, String, String, SD)
472     * @see Torello.HTML.HTMLNode#str
473     */
474    ConcatToEndOrSet,
475
476    /**
477     * This {@code AUM} enumerated type is precisely identical to the one named {@code ConcatToEnd}
478     * - <I><B>except</B></I> that in the case where the inner-tag <B STYLE="color: red;">value</B>
479     * is appended, a space is added immediately before the newly added
480     * {@code String}-<B STYLE="color: red;">value</B> token.
481     * 
482     * <BR /><BR /><DIV CLASS=JDHint>
483     * The primary reason for adding this surprisingly subtle and minor difference is to remind
484     * users that keeping up with spaces when tweaking HTML inner-tags can be a bug source.
485     * </DIV>
486     *
487     * <BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
488     * 
489     * <DIV CLASS=SNIP>{@code
490     * // String cur = tn.AV(innerTag);
491     * case ConcatToEndAddSpace: return (cur != null) 
492     *     ? tn.setAV(innerTag, cur + ' ' + innerTagValue, quote)
493     *     : null;
494     * }</DIV>
495     *
496     * <DIV CLASS=EXAMPLE>{@code
497     * // Example 1
498     * String   innerTag        = "id";
499     * String   innerTagValue   = "JAVA-AUM-EXAMPLE";
500     * AUM      mode            = AUM.ConcatToEndAddSpace;
501     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
502     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
503     * // newTN                 ==> null
504     *                          // NOTE: HTML Element left unchanged, because it did not actually
505     *                          //       have an 'id' attribute in the first place. 
506     *                          //       A return value of 'null' implies this AUM does not result
507     *                          //       in a replacement or update for the TagNode passed.
508     *
509     * // Example 2
510     * String   innerTag        = "id";
511     * String   innerTagValue   = "JAVA-AUM-EXAMPLE";
512     * AUM      mode            = AUM.ConcatToEndAddSpace;
513     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ID='MyClass'>");
514     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
515     * // newTN.str             ==> <IMG SRC='img-123.jpg' id='MyClass JAVA-AUM-EXAMPLE'>
516     * }</DIV>
517     * 
518     * @see #update(TagNode, String, String, SD)
519     * @see Torello.HTML.HTMLNode#str
520     */
521    ConcatToEndAddSpace,
522
523    /**
524     * This {@code AUM} enumerated type is precisely identical to the one named {@code ConcatToEnd}
525     * - <I><B>except</B></I> that in the case where the inner-tag <B STYLE="color: red;">value</B>
526     * is appended, a space is added immediately before the newly added
527     * {@code String}-<B STYLE="color: red;">value</B> token.
528     *
529     * <BR /><BR /><DIV CLASS=JDHint>
530     * If there were no inner-tag <B STYLE="color: red;">key-value</B> pair, and a new one was
531     * added - then an extra space would, hopefully this is obvious, <B>then an extra space would
532     * not be needed</B>, and therefore it is not added.
533     * </DIV>
534     *
535     * <BR /><B CLASS=JDDescLabel>How the Attribute-Update is Done:</B>
536     * 
537     * <DIV CLASS="SNIP">{@code
538     * // String cur = tn.AV(innerTag);
539     * case ConcatToEndOrSetAddSpace: return (cur != null)
540     *     ? tn.setAV(innerTag, cur + ' ' + innerTagValue, quote)
541     *     : tn.setAV(innerTag, innerTagValue, quote);
542     * }</DIV>
543     *
544     * <DIV CLASS=EXAMPLE>{@code
545     * // Example 1
546     * String   innerTag        = "alt";
547     * String   innerTagValue   = "This is a corporate photo.";
548     * AUM      mode            = AUM.ConcatToEndOrSetAddSpace;
549     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg'>");
550     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
551     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='This is a corporate photo.'> 
552     *
553     * // Example 2
554     * String   innerTag        = "alt";
555     * String   innerTagValue   = "This is a corporate photo.";
556     * AUM      mode            = AUM.ConcatToEndOrSetAddSpace;
557     * TagNode  tn              = new TagNode("<IMG SRC='img-123.jpg' ALT='Bob'>");
558     * TagNode  newTN           = mode.update(tn, innerTag, innerTagValue, SD.SingleQuote);
559     * // newTN.str             ==> <IMG SRC='img-123.jpg' alt='Bob - This is a corporate photo.'
560     * }</DIV>
561     * 
562     * @see #update(TagNode, String, String, SD)
563     * @see Torello.HTML.HTMLNode#str
564     */
565    ConcatToEndOrSetAddSpace;
566
567    /**
568     * This performs the Update corresponding to the Attribute-Update-Mode for the particular
569     * AUM instance for {@code 'this'} enumerated-type object reference.
570     * 
571     * @param tn This HTML Element TagNode on which the update shall be performed.
572     * @param innerTag The Inner-Tag Key Name to look for inside the HTML Element. 
573     * @param innerTagValue The Inner-Tag Value to update, remove, concatenate, append or set.
574     * 
575     * @param quote This is a major issue in HTML / Java Programming.  The best thing to do is
576     * to not try to solve this problem at the lower-level, but rather propagate it up.
577     * 
578     * @return a newly updated or modified TagNode reference object.  If the update mode did not
579     * permit an attribute removal, update, or addition, then 'null' shall be returned.  Again,
580     * if 'null' is returned, it means the TagNode did not change - or, rather - <I>did not need
581     * to be changed as per the requirements of the chosen Attribute Update Method (AUM).</I>
582     */
583    public final TagNode update(TagNode tn, String innerTag, String innerTagValue, SD quote)
584    {
585        String cur = tn.AV(innerTag);
586
587        switch (this)
588        {
589            case Set: return tn.setAV(innerTag, innerTagValue, quote);
590
591            case Replace: return (cur != null)
592                ? tn.setAV(innerTag, innerTagValue, quote)
593                : null;
594
595            case RemoveSubString: return ((cur != null) && (cur.indexOf(innerTagValue) != -1))
596                ? tn.setAV(innerTag, cur.replace(innerTagValue, ""), quote)
597                : null;
598
599            case RemoveSubString_CI:
600                int i;
601
602                return ((cur != null) && ((i = StrIndexOf.first_CI(cur, innerTagValue)) != -1))
603
604                    ? (tn.setAV(innerTag, cur.substring(0, i) + 
605                      cur.substring(i + innerTagValue.length()), quote))
606
607                    : null;
608
609            case ConcatToStart: return (cur != null)
610                ? tn.setAV(innerTag, innerTagValue + cur, quote)
611                : null;
612
613            case ConcatToStartOrSet: return (cur != null)
614                ? tn.setAV(innerTag, innerTagValue + cur, quote)
615                : tn.setAV(innerTag, innerTagValue, quote);
616
617            case ConcatToStartAddSpace: return (cur != null)
618                ? tn.setAV(innerTag, innerTagValue + ' ' + cur, quote)
619                : null;
620
621            case ConcatToStartOrSetAddSpace: return (cur != null)
622                ? tn.setAV(innerTag, innerTagValue + ' ' + cur, quote)
623                : tn.setAV(innerTag, innerTagValue, quote);
624
625            case ConcatToEnd: return (cur != null)
626                ? tn.setAV(innerTag, cur + innerTagValue, quote)
627                : null;
628
629            case ConcatToEndOrSet: return (cur != null)
630                ? tn.setAV(innerTag, cur + innerTagValue, quote)
631                : tn.setAV(innerTag, innerTagValue, quote);
632
633            case ConcatToEndAddSpace: return (cur != null)
634                ? tn.setAV(innerTag, cur + ' ' + innerTagValue, quote)
635                : null;
636
637            case ConcatToEndOrSetAddSpace: return (cur != null)
638                ? tn.setAV(innerTag, cur + ' ' + innerTagValue, quote)
639                : tn.setAV(innerTag, innerTagValue, quote);
640
641            default: throw new UnreachableError();
642        }
643    }
644}