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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package Torello.JDUInternal.Annotations;

import Torello.HTML.NodeSearch.CSSStrException;
import Torello.Java.Additional.EffectivelyFinal;
import Torello.Java.StringParse;

import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;

import javax.tools.Diagnostic;

/**
 * Annotation Processor for the {@link JDHeaderBackgroundImg} Annotation.
 */
class JDHBImgProcessor
{
    // This implements the processing for the Annotation @JDHeaderBackgroundImg.
    // It does validity checks on the parameter input.

    static boolean process
        (Element ciet, AnnotationMirror am, javax.annotation.processing.Messager messager)
    {
        EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false);

        am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) ->
        {
            // This is the "thing-y" inside the Annotation.  It is called a "Member" by the
            // Annotation-Processor.  It is called a "Required-Element" or "Optional-Element" in a
            // Java-Doc Web-Page.  Understanding the 'terminology' in Annotations and Annotation
            // Processor's is half of the work in using it.  In the JD Upgrader Package (this 
            // Package), these are "Entity" - Entity.ANNOTATION_ELEM
            //
            // In **THIS** Annotation (JDHeaderBackgroundImg), the two Elements (Members / Entites)
            // are "CSSClass" and "EmbedTagFiledID"

            String memberName = ee.toString();

            // The value assigned to this Member.  In the @JDHeaderBackgroundImg, both of the
            // "Members" or "Elements" (whichever of the many terms is more appealing) that are
            // defined - are both listed (inside the Annotation-Definition '.java' file) as
            // **String-Arrays**.  Here, in the Annotation-Processor, their values will be returned
            // as instances of:
            //
            // com.sun...List - a class which implements the "java.util.List" class.
            // But is not actually included by the JDK!

            Object val = av.getValue();


            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Java Assertion.  This Really **SHOULD** Hold, but just in case....
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            if (! java.util.List.class.isAssignableFrom(val.getClass()))

                // Don't use the Messager, this is a "Java-Error" (or else I'm just not quite
                // understanding Annotations-Processors yet)

                throw new InternalError(
                    memberName + " Annotation-Element-Value Type is not a List, " +
                    '[' + val.getClass().getName() + ']'
                );

            List<?> list = (List) val;


            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
            // Dispatch to either the handler for "CSSClass" or "EmbedTagFileID"
            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

            switch (memberName)
            {
                case "CSSClass()" :
                    errors.f |= checkCSSClass(list, messager);  break;

                case "EmbedTagFileID()" :

                    // This was moved to the main class, since this method which checks the 
                    // FILE-ID for validity is reused by the AutoFindID Annotation as well.
                    // Both of these Annotations which use this method are checking for the exact
                    // same thing, so there is no reason to keep them separate.

                    errors.f |= JDUAnnotationProcessorDispatch.checkFileID(list, messager);    break;

                default: 

                    // If the 'javac' (Java-Compiler) Annotation-Processing Whole-Mechanism Thingy
                    // is working, the only two Annotation-Elements that could possibly be sent to
                    // this loop are the two listed above...  These two "Elements" or "Members"
                    // "Entites" (I'll say this again) are the ones defined inside the '.java'
                    // File having name "JDHeaderBackgroundImg.java".  The Java-Doc Page for them
                    // explains (very well) the two Array-Parameter Elements
                    //
                    // This should be UNREACHABLE-CODE.  The Java-Compiler, itself, should do the
                    // complaining that the user has provided an Annotation-Member that is not
                    // listed inside the definition for that Annotation.
                    //
                    // Don't use the Messager, this simply cannot happen unless I'm just not 
                    // understanding all of the nuances of this stuff-ola.
            
                    throw new InternalError(
                        "\tThere was an annotation parameter whose name wasn't recognized: " +
                        ee.toString() + "\n" +
                        "\tThe only parameter's that may be passed to @JDHeaderBackgroundImg " +
                        "are 'CSSClass' and 'EmbedTagFileID'\n"
                    );
            }
        });

        return errors.f;
    }

    // Check each of the User-Provided "<DIV> CLASS's".  There is a Predicate-Checker
    // inside the NodeSearch Package for CSS-CLASS Strings

    private static boolean checkCSSClass
        (List<?> list, javax.annotation.processing.Messager messager)
    {
        String classStr;
        boolean errors = false;

        for (Object classObj : list)

            // In Java 11, this returns a quoted-string, and in Java 17, there were no quotes
            if ((classStr = StringParse.ifQuotesStripQuotes(classObj.toString())).length() > 0)

                // Predicate for checking Valid CSS-Class Names
                if (! CSSStrException.VALID_CSS_CLASS_OR_NAME_TOKEN_PRED.test(classStr))

                {
                    // Don't Return Immediately, Check all of the CSS-Classes (in case there are
                    // more than one defined).  AGAIN: It is always better to print as many errors
                    // as possible during each phase of compilation, so that the end-user doesn't
                    // have to keep typing 'javac'

                    messager.printMessage
                        (Diagnostic.Kind.ERROR, "Invalid CSS Class-Name: [" + classStr + "]");

                    errors = true;
                }

        return errors;
    }
}