001package Torello.JavaDoc.Annotations;
002
003import Torello.Java.StrSource;
004import Torello.Java.StrCh;
005import Torello.Java.StringParse;
006
007import Torello.Java.Additional.EffectivelyFinal;
008
009import javax.annotation.processing.Messager;
010
011import javax.lang.model.element.Element;
012import javax.lang.model.element.ExecutableElement;
013import javax.lang.model.element.AnnotationMirror;
014import javax.lang.model.element.AnnotationValue;
015
016import javax.tools.Diagnostic;
017
018import java.util.List;
019import java.util.Arrays;
020
021import java.util.stream.Stream;
022
023// EXPORTS:
024//      public Background background() default Background.Blue;
025//      public String title() default "";
026//      public String divCSSClass() default "";
027//      public String tableCSSClass() default "";
028// 
029// 
030// The following files are relatedf to this 'javac' Annotation-Processor:
031// 
032// * Torello.JDUInternal.SimpleFeatures.IntoHTMLTableProc
033//      This is the primary or "Work Horse" Method for Generating the HTML-Table that is inserted
034//      into the Detail-Entry "description()" section.
035// 
036// * User-Annotations.css
037//      For the CSS Color Choices/Options/Definitions
038//      Since there are a suite of Color-Choices which have been presented to the user
039
040
041@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="ANNOT_PROC_JDHBI")
042public class IHTProcessor
043{
044    private IHTProcessor() { }
045
046    // This is used by the Error-Message Printer
047    private static final String IHT_NAME =
048        Torello.JavaDoc.Annotations.IntoHTMLTable.class.getSimpleName();
049
050    // @IntoHTMLTable Annotation:
051    // 
052    // EXPORTS:
053    //      public Background background() default Background.Blue;
054    //      public String title() default "";
055    //      public String divCSSClass() default "";
056    //      public String tableCSSClass() default "";
057
058    static boolean process(
059            Element             ciet,
060            AnnotationMirror    am,
061            javax.annotation.processing.Messager messager
062        )
063    {
064        EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false);
065
066        am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) ->
067        {
068            // Understanding the 'terminology' in Annotations and Annotation-Processor's is half of
069            // the work in using it.
070
071            final Object val  = av.getValue();
072
073            switch (ee.toString())
074            {
075                case "background()" :
076                    break;
077
078                case "title()" :
079                    errors.f |= checkTitleAE(messager, ciet, (String) val);
080                    break;
081
082                case "divCSSClass()" :
083                    errors.f |= checkCSSClassAE(messager, ciet, "divCSSClass()", (String) val);
084                    break;
085
086                case "tableCSSClass()" :
087                    errors.f |= checkCSSClassAE(messager, ciet, "divCSSClass()", (String) val);
088                    break;
089
090                default: 
091
092                    // This should be UNREACHABLE-CODE.  The Java-Compiler, itself, should do the
093                    // complaining that the user supplied an Annotation-Element name that is not
094                    // among those listed above.  Unless 'javac' changes, this cannot execute.
095
096                    throw new InternalError(
097                        "There was an annotation parameter whose name wasn't recognized: " +
098                        ee.toString() + "\n" +
099                        "The only parameter's that may be passed to @IntoHTMLTable are:\n" +
100                        "'background()', 'title()', 'divCSSClass()' and 'tableCSSClass()'"
101                    );
102            }
103        });        
104
105        return errors.f;
106    }
107
108
109    // ********************************************************************************************
110    // ********************************************************************************************
111    // Checks both the "name()" and "handle()" Annotation-Elements
112    // ********************************************************************************************
113    // ********************************************************************************************
114
115
116    private static boolean checkTitleAE(
117            javax.annotation.processing.Messager messager,
118            Element ciet,
119            String  aeValAsStr
120        )
121    {
122        // THIS TEST IS BLOCK-COPIED IDENTICAL TO THE TEST THAT IS LOCATED INSIDE
123        // "Torello.JDUInternal.Annotations.EntityAnnotations.Mirror.IHTErrorCheck"
124
125        final boolean test =
126                (! StrCh.containsOR(aeValAsStr, '\t', '\n', '\r'))
127            &&  (aeValAsStr.length() <= 300);
128
129        if (test) return true;
130
131        // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t'
132        messager.printMessage(
133            Diagnostic.Kind.ERROR,
134            HELPER.LOCATION(ciet, IHT_NAME) +
135            "\tString Annotation-Parameter 'title()' was passed " +
136                "[" + aeValAsStr + "]\n" +
137            "\tHowever, this String may not contain the characters: '\\t', '\\n', '\\r'\n" +
138            "\tNor may it be more than 300 Characters long."
139        );
140
141        return false;
142    }
143
144
145    // ********************************************************************************************
146    // ********************************************************************************************
147    // Checks the "typeName()" Annotation-Elements
148    // ********************************************************************************************
149    // ********************************************************************************************
150
151
152    private static boolean checkCSSClassAE(
153            final javax.annotation.processing.Messager messager,
154            final Element   ciet,
155            final String    aeName,
156            final String    aeValAsStr
157        )
158    {
159        if (aeValAsStr.length() == 0) return true;
160
161        final String[] cssClasses = aeValAsStr.split("\\s");
162
163        final Stream.Builder<String> b = Stream.builder();
164
165        boolean errors = false;
166
167        for (final String cssClass : cssClasses)
168
169            if (! StrSource.isCSSClassName(cssClass))
170            {
171                b.accept(cssClass);
172                errors = true;
173            }
174
175        if (! errors) return true;
176
177        messager.printMessage(
178            Diagnostic.Kind.ERROR,
179            HELPER.LOCATION(ciet, IHT_NAME) +
180
181            // NOTE: Torello.JDUInternal.Messager **DOES NOT** ALLOW '\t'
182            "\tString Annotation-Parameter " + aeName + " was passed " +
183                "[" + aeValAsStr + "]\n" +
184            "\tHowever, the following CSS-Classes are invalid CSS Class-Names:\n" +
185            Arrays.toString(b.build().toArray())
186        );
187
188        return false;
189    }
190}