001package Torello.JavaDoc.Annotations;
002
003import Torello.Java.Additional.EffectivelyFinal;
004import Torello.Java.StringParse;
005
006import java.io.File;
007import java.util.List;
008import java.net.URI;
009
010import javax.annotation.processing.Filer;
011
012import javax.lang.model.element.Element;
013import javax.lang.model.element.ExecutableElement;
014import javax.lang.model.element.AnnotationMirror;
015import javax.lang.model.element.AnnotationValue;
016
017import javax.tools.Diagnostic;
018import javax.tools.JavaFileObject;
019
020
021// EXPORTS:
022//      public String[] FileNames();
023// 
024// package Torello.JDUInternal.Features.USER_SUPPLIED_CSS_FILES
025//      The classes in this package do the processing for inserting the '.css' Files which the user
026//      has requested be placed into his Java-Doc '.html' Web-Page.  These '.css' Files must be
027//      located in the '../upgrade-files/stylesheets/' directory.  These '.css' Files must either:
028// 
029//          1) obey the standard naming convention and have the exact same file-name as the
030//          Java-Class which has been annotated by the @CSSLinks Annotation
031// 
032//          2) have a name equal to one of the names provided to the Annotation-Element "FileNames"
033
034
035@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="ANNOT_PROC_JDHBI")
036public class CSSLProcessor
037{
038    private CSSLProcessor() { }
039
040    // This is used by the Error-Message Printer
041    private static final String CSSLINKSNAME =
042        Torello.JavaDoc.Annotations.CSSLinks.class.getSimpleName();
043
044    // This implements the processing for the Annotation @JDHeaderBackgroundImg.
045    // It does validity checks on the parameter input.
046
047    private static final String FS = File.separator;
048
049    static boolean process(
050            Element                                 ciet, 
051            AnnotationMirror                        am,
052            Filer                                   filer,
053            javax.annotation.processing.Messager    messager
054        )
055    {
056        /*
057        try
058        {
059            // This will have the Complete-Name of the Annotated CIET/Type
060            //
061            // NOTE: Currently, I have no idea how to tell which part is a "Package-Name", and
062            //       which part is a "Container-Class"
063            //
064            // Is Torello.Java.Additional.ReadJSON.XL a class that is inside 
065            // sub-package ReadJSON or container-class ReadJSON
066            //
067            // This has to stop for now, this will be easier to work with once I have finished the
068            // new Build classes
069
070            String typeName = ciet.asType().toString();
071
072            // THEORETICALLY, This should be a file inside the same directory as the .java file
073            JavaFileObject sourceFile = filer.createSourceFile(typeName + "$Dummy");
074
075            // THEREFORE, NO (AGAIN, THEORETICALLY), THIS HOLDS THE FILE-NAME NO MATTER WHERE THIS
076            // FILE IS LOCATED INSIDE THE CLASS-PATH.
077            String filePath = sourceFile.toUri().getPath();
078
079            // NO IDEA WHAT THIS IS DOING
080            sourceFile.delete();
081
082            messager.printMessage(
083                Diagnostic.Kind.NOTE,    
084                HELPER.LOCATION(ciet, CSSLINKSNAME) +
085                "    Path: " + filePath
086            );
087        }
088
089        catch (Exception e)
090        {
091
092        }
093        */
094
095        EffectivelyFinal<Boolean> errors = new EffectivelyFinal<>(false);
096
097        am.getElementValues().forEach((ExecutableElement ee, AnnotationValue av) ->
098        {
099            // This is the "thing-y" inside the Annotation.  It is called a "Member" by the
100            // Annotation-Processor.  It is called a "Required-Element" or "Optional-Element" in a
101            // Java-Doc Web-Page.  Understanding the 'terminology' in Annotations and Annotation
102            // Processor's is half of the work in using it.  In the JD Upgrader Package (this 
103            // Package), these are "Entity" - Entity.ANNOTATION_ELEM
104            //
105            // In **THIS** Annotation (CSSLinks), there is only one Element / Member / Entity,
106            // and its name is "FileName"
107
108            String memberName = ee.toString();
109
110            // The value assigned to this Member.  In the @CSSLinks, the "Member" or "Element"
111            // (whichever of the many terms is more appealing) that's defined - is listed (inside
112            // the Annotation-Definition '.java' file) as a **String-Array**.  Here, in the
113            // Annotation-Processor, its value will be returned as an instances of:
114            //
115            // com.sun...List - a class which implements the "java.util.List" class.
116            // But is not actually included by the JDK!
117
118            Object val = av.getValue();
119
120
121            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
122            // Java Assertion.  This Really **SHOULD** Hold, but just in case....
123            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
124
125            if (! java.util.List.class.isAssignableFrom(val.getClass()))
126
127                // Don't use the Messager, this is a "Java-Error" (or else I'm just not quite
128                // understanding Annotations-Processors yet)
129
130                throw new InternalError(
131                    memberName + " Annotation-Element-Value Type is not a List, " +
132                    '[' + val.getClass().getName() + ']'
133                );
134
135            List<?> list = (List) val;
136
137
138            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
139            // Dispatch to the handler for "FileNames"
140            // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
141
142            switch (memberName)
143            {
144                case "FileNames()" :
145                    errors.f |= checkCSSFile(ciet, list, messager);  break;
146
147                default: 
148
149                    // If the 'javac' (Java-Compiler) Annotation-Processing Whole-Mechanism Thingy
150                    // is working, the only two Annotation-Elements that could possibly be sent to
151                    // this loop are the two listed above...  These two "Elements" or "Members"
152                    // "Entites" (I'll say this again) are the ones defined inside the '.java'
153                    // File having name "JDHeaderBackgroundImg.java".  The Java-Doc Page for them
154                    // explains (very well) the two Array-Parameter Elements
155                    //
156                    // This should be UNREACHABLE-CODE.  The Java-Compiler, itself, should do the
157                    // complaining that the user has provided an Annotation-Member that is not
158                    // listed inside the definition for that Annotation.
159                    //
160                    // Don't use the Messager, this simply cannot happen unless I'm just not 
161                    // understanding all of the nuances of this stuff-ola.
162            
163                    throw new InternalError(
164                        "There was an annotation parameter whose name wasn't recognized: " +
165                        ee.toString() + "\n" +
166                        "The only parameter that may be passed to @CSSFiles is 'FileNames\n'"
167                    );
168            }
169        });
170
171        return errors.f;
172    }
173
174    private static final String curDir()
175    { return "THIS PART ISN'T WORKING AT THE MOMENT"; }
176
177    // Check each of the User-Provided "<DIV> CLASS's".  There is a Predicate-Checker
178    // inside the NodeSearch Package for CSS-CLASS Strings
179
180    private static boolean checkCSSFile
181        (Element ciet, List<?> list, javax.annotation.processing.Messager messager)
182    {
183        String fileName;
184        boolean errors = false;
185
186        for (Object fileNameObj : list)
187
188            // In Java 11, this returns a quoted-string, and in Java 17, there were no quotes
189            if ((fileName = StringParse.ifQuotesStripQuotes(fileNameObj.toString())).length() > 0)
190            {
191                String fullPathName = null;
192                boolean relativeOrAbsolute;
193                File file;
194
195
196                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
197                // Identify the actual Full-Path Name of the File
198                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
199                //
200                // Get the Full-Path Name for this File - regardless of whether the File-String
201                // provided by the user is a relative File-Name, or an absolute File-Name
202
203                if (fileName.contains(File.separator))
204                {
205                    relativeOrAbsolute  = false;
206                    fullPathName        = fileName;
207                }
208
209                else
210                {
211                    relativeOrAbsolute = true;
212
213                    fullPathName = curDir() + FS + "upgrade-files" + FS + "stylesheets" + FS + 
214                        fileName;
215                }
216
217                // In it's current incarnation, there is simply no way to get the relative
218                // directory where a Source-File is located.  In all actuallity, it isn't going to
219                // matter much anyway, since finding the /upgrade-files/stylesheets just isn't
220                // going to work at the present moment.
221
222                if (relativeOrAbsolute) continue;
223
224
225                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
226                // Check that the file actually exists on the File-System, and if not, flag error
227                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
228
229                try
230                {
231                    file = new File(fullPathName);
232
233                    if (! file.exists())
234                    {
235                        messager.printMessage(
236                            Diagnostic.Kind.ERROR,    
237                            HELPER.LOCATION(ciet, CSSLINKSNAME) +
238                            "    [" + fileName + "]\n    File not found" +
239                            (relativeOrAbsolute
240                                ? " in the upgrade-files/stylesheets/ directory"
241                                : ""
242                            )
243                        );
244
245                        errors = true;
246                        continue;
247                    }
248                }
249
250                catch (Exception e)
251                {
252                    messager.printMessage(
253                        Diagnostic.Kind.ERROR,
254                        HELPER.LOCATION(ciet, CSSLINKSNAME) +
255                        "Exception thrown attempting to open / locate File:\n[" + fileName + "]\n" +
256                        "    e.getClass():   " + e.getClass().getName() + 'n' +
257                        "    e.getMessage(): " + e.getMessage() + '\n'
258                    );
259
260                    errors = true;
261                    continue;
262                }
263
264
265                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
266                // Make sure that the specified File is not a Directory, otherwise Flag and Error
267                // *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
268
269                try
270                {
271                    if (file.isDirectory())
272                    {
273                        messager.printMessage(
274                            Diagnostic.Kind.ERROR,
275                            HELPER.LOCATION(ciet, CSSLINKSNAME) +
276                            "[" + fileName + "] seems to specify a Directory, rather than a File."
277                        );
278
279                        errors = true;
280                        continue;
281                    }
282                }
283
284                catch (Exception e)
285                {
286                    messager.printMessage(
287                        Diagnostic.Kind.ERROR,
288                        HELPER.LOCATION(ciet, CSSLINKSNAME) +
289                        "Exception thrown attempting to open / locate File:\n[" + fileName + "]\n" +
290                        "    e.getClass():   " + e.getClass().getName() + 'n' +
291                        "    e.getMessage(): " + e.getMessage() + '\n'
292                    );
293
294                    errors = true;
295                    continue;
296                }
297            }
298
299        return errors;
300    }
301
302}