001package Torello.JavaDoc.Annotations;
002
003import Torello.HTML.NodeSearch.CSSStrException;
004import Torello.Java.Additional.EffectivelyFinal;
005import Torello.Java.StringParse;
006
007import java.util.List;
008
009import javax.lang.model.element.Element;
010import javax.lang.model.element.ExecutableElement;
011import javax.lang.model.element.AnnotationMirror;
012import javax.lang.model.element.AnnotationValue;
013
014import javax.tools.Diagnostic;
015
016// EXPORTS:
017//      String[] CSSClass() default { };
018//      String[] EmbedTagFileID() default { };
019// 
020// package Torello.JDUInternal.Features.EXTERNAL_HTML_FILES
021//      The classes in this package do the processing for inserting the HTML from External-HTML
022//      Files into Java-Doc '.html' Output-Files.  It places an HTML <IMG SRC=...> at the top of
023//      the page.  The Imge contains a Wooden-Panel, and the User's JDHBI HTML for that class is 
024//      then placed on top of / over the Wood-Paneling
025
026
027@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="ANNOT_PROC_JDHBI")
028public class JDHBIProcessor
029{
030    private JDHBIProcessor() { }
031
032    // This implements the processing for the Annotation @JDHeaderBackgroundImg.
033    // It does validity checks on the parameter input.
034
035    static boolean process
036        (Element ciet, AnnotationMirror am, javax.annotation.processing.Messager messager)
037    {
038        final EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false);
039
040        am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) ->
041        {
042            // This is the "thing-y" inside the Annotation.  It is called a "Member" by the
043            // Annotation-Processor.  It is called a "Required-Element" or "Optional-Element" in a
044            // Java-Doc Web-Page.  Understanding the 'terminology' in Annotations and Annotation
045            // Processor's is half of the work in using it.  In the JD Upgrader Package (this 
046            // Package), these are "Entity" - Entity.ANNOTATION_ELEM
047            //
048            // In **THIS** Annotation (JDHeaderBackgroundImg), the two Elements (Members / Entites)
049            // are "CSSClass" and "EmbedTagFiledID"
050
051            String memberName = ee.toString();
052
053            // The value assigned to this Member.  In the @JDHeaderBackgroundImg, both of the
054            // "Members" or "Elements" (whichever of the many terms is more appealing) that are
055            // defined - are both listed (inside the Annotation-Definition '.java' file) as
056            // **String-Arrays**.  Here, in the Annotation-Processor, their values will be returned
057            // as instances of:
058            //
059            // com.sun...List - a class which implements the "java.util.List" class.
060            // But is not actually included by the JDK!
061
062            Object val = av.getValue();
063
064
065            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
066            // Java Assertion.  This Really **SHOULD** Hold, but just in case....
067            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
068
069            if (! java.util.List.class.isAssignableFrom(val.getClass()))
070
071                // Don't use the Messager, this is a "Java-Error" (or else I'm just not quite
072                // understanding Annotations-Processors yet)
073
074                throw new InternalError(
075                    memberName + " Annotation-Element-Value Type is not a List, " +
076                    '[' + val.getClass().getName() + ']'
077                );
078
079            List<?> list = (List) val;
080
081
082            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
083            // Dispatch to either the handler for "CSSClass" or "EmbedTagFileID"
084            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
085
086            switch (memberName)
087            {
088                case "CSSClass()" :
089                    errors.f |= checkCSSClass(list, messager);  break;
090
091                case "EmbedTagFileID()" :
092
093                    // This was moved to the main class, since this method which checks the 
094                    // FILE-ID for validity is reused by the AutoFindID Annotation as well.
095                    // Both of these Annotations which use this method are checking for the exact
096                    // same thing, so there is no reason to keep them separate.
097
098                    errors.f |= HELPER.checkFileID(list, messager);    break;
099
100                default: 
101
102                    // If the 'javac' (Java-Compiler) Annotation-Processing Whole-Mechanism Thingy
103                    // is working, the only two Annotation-Elements that could possibly be sent to
104                    // this loop are the two listed above...  These two "Elements" or "Members"
105                    // "Entites" (I'll say this again) are the ones defined inside the '.java'
106                    // File having name "JDHeaderBackgroundImg.java".  The Java-Doc Page for them
107                    // explains (very well) the two Array-Parameter Elements
108                    //
109                    // This should be UNREACHABLE-CODE.  The Java-Compiler, itself, should do the
110                    // complaining that the user has provided an Annotation-Member that is not
111                    // listed inside the definition for that Annotation.
112                    //
113                    // Don't use the Messager, this simply cannot happen unless I'm just not 
114                    // understanding all of the nuances of this stuff-ola.
115            
116                    throw new InternalError(
117                        "There was an annotation parameter whose name wasn't recognized: " +
118                        ee.toString() + "\n" +
119                        "The only parameter's that may be passed to @JDHeaderBackgroundImg " +
120                        "are 'CSSClass' and 'EmbedTagFileID'\n"
121                    );
122            }
123        });
124
125        return errors.f;
126    }
127
128    // Check each of the User-Provided "<DIV> CLASS's".  There is a Predicate-Checker
129    // inside the NodeSearch Package for CSS-CLASS Strings
130
131    private static boolean checkCSSClass
132        (List<?> list, javax.annotation.processing.Messager messager)
133    {
134        String classStr;
135        boolean errors = false;
136
137        for (Object classObj : list)
138
139            // In Java 11, this returns a quoted-string, and in Java 17, there were no quotes
140            if ((classStr = StringParse.ifQuotesStripQuotes(classObj.toString())).length() > 0)
141
142                // Predicate for checking Valid CSS-Class Names
143                if (! CSSStrException.VALID_CSS_CLASS_OR_NAME_TOKEN_PRED.test(classStr))
144
145                {
146                    // Don't Return Immediately, Check all of the CSS-Classes (in case there are
147                    // more than one defined).  AGAIN: It is always better to print as many errors
148                    // as possible during each phase of compilation, so that the end-user doesn't
149                    // have to keep typing 'javac'
150
151                    messager.printMessage
152                        (Diagnostic.Kind.ERROR, "Invalid CSS Class-Name: [" + classStr + "]");
153
154                    errors = true;
155                }
156
157        return errors;
158    }
159}
160