001package Torello.Browser.JsonAST;
002
003import Torello.Java.ReadOnly.ReadOnlyList;
004import Torello.Java.UnreachableError;
005
006/**
007 * This class generates the "Computed Type as String" for a {@link PPR} instance.
008 * <EMBED CLASS='external-html' DATA-FILE-ID=PPR_CTAS>
009 */
010@Torello.JavaDoc.Annotations.StaticFunctional
011@Torello.JavaDoc.Annotations.JDHeaderBackgroundImg(EmbedTagFileID="LINKER_JDHBI")
012public class PPR_CTAS
013{
014    private PPR_CTAS() { }
015
016    // REMEMBER:
017    // 
018    //  1) Both TypeNode's and PPR's have a CTAS / CTAB field
019    // 
020    //  2) TypeNode's CTAS / CTAB can be computed inside their constructors.  They don't need some
021    //     complicated "Linking Stage".  TypeNode's either 'degenerate' into a simple Java type
022    //     such as 'java.lang.Sting', or they specify their own, predfined, CDP Browser Type.
023    // 
024    //  3) TypeNode's never default to being some other CDP defined TypeNode within CDP, that would
025    //     make zero sense at all !  (NOTE: There is one lone / hold-out special case which I'm 
026    //     simple not going to mention here - "ArrayOfString" - but that's all I'll say...)
027    // 
028    //      i)      Thusly TypeNode's don't have to wait until all of the other TypeNode's have
029    //              been constructed to set their values.
030    // 
031    //      ii)     Thusly their CTAS / CTAB values can be set, instantaneously, inside thier ctors
032    // 
033    //      III)    Thusly CTAS / CTAB fields inside of 'TypeNode' can be declared final and can 
034    //              avoid a complicated "Link Phase" analysis.
035    // 
036    //  4) PPR's can deflate into simple Java Types.  But they can also deflate into other CDP
037    //     defined Types.  Thusly, they have to wait for the entire AST to be built before they can
038    //     have values assigned to their CTAS / CTAB fields or their 'reference' & 'referenceArray'
039    //     fields.
040    // 
041    //  PPR's *HAVE TO WAIT* for all TypeNode's to be constructed before they can be linked!
042
043    static void iterateSetCTAS(final API api)
044    { for (final Domain d : api.domains) iterateSetCTAS(d); }
045
046    private static void iterateSetCTAS(final Domain d)
047    {
048        for (final TypeNode type    : d.types)  iterateSetCTAS(type.properties);
049        for (final EventNode event  : d.events) iterateSetCTAS(event.parameters);
050
051        for (final CommandNode command : d.commands)
052        {
053            iterateSetCTAS(command.parameters);
054            iterateSetCTAS(command.returns);
055        }
056    }
057
058    private static void iterateSetCTAS(final ReadOnlyList<PPR> rol)
059    {
060        if (rol != null)
061            for (final PPR ppr : rol)
062                ppr.setCTAS(ctas(ppr));
063    }
064
065
066    // This is one of the center-piece methods for the JsonAST package.  This converts all of the
067    // fields inside of class PPR into a String that may be used by the Code-Generator package to
068    // generate an actual type for whatever Method-Parameter or Class-Field which this PPR instance
069    // ultimately represents.
070    // 
071    // This called a "Center-Piece" becuase the "linking" really is that difficult to explain in
072    // my mind.  It took a long time to fully understand what my code was really doing.
073
074    private static String ctas(final PPR ppr)
075    {
076        final TypeNode REFERENCE        = ppr.reference();
077        final TypeNode REFERENCE_ARR    = ppr.referenceArray();
078
079        if (REFERENCE_ARR != null) return REFERENCE_ARR.isReifiedInnerClass
080            ? REFERENCE_ARR.CTAS + "[]"
081            : ARRAY_OF_STUFFOLA(REFERENCE_ARR.CTAS);
082
083        else if (REFERENCE != null) return REFERENCE.isReifiedInnerClass
084            ? REFERENCE.CTAS
085            : STUFFOLA(ppr, REFERENCE.CTAS);
086
087        else if (ppr.arrItemsTypeProp != null)
088            return ppr.arrItemsTypeProp.arrayCTAS.getSimpleName();
089
090        else if (ppr.typeProp != null) return ppr.optional 
091            ? ppr.typeProp.boxedCTAS.getSimpleName()
092            : ppr.typeProp.primCTAS.getSimpleName();
093
094        else throw new UnreachableError();
095    }
096
097
098    // I choose to call this "stuffola" for a very precise and scientific reason
099    // But I'm not going to tell you that reason, not now, not today.
100    // Damn it Jim, I am just a doctor, not a miracle worker!
101
102    private static String STUFFOLA(final PPR ppr, final String ctas)
103    {
104        switch (ctas) 
105        {
106            case "int" :        return ppr.optional ? "Integer" : "int";
107            case "boolean" :    return ppr.optional ? "Boolean" : "boolean";
108        
109            default: return ctas;
110        }
111
112    }
113
114    private static String ARRAY_OF_STUFFOLA(final String ctas)
115    {
116        switch (ctas)
117        {
118            case "JsonValue":   return "JsonValue";
119            case "Integer":     return "int[]";
120            case "Boolean":     return "boolean[]";
121    
122            default: return ctas + "[]";
123        }
124    }
125}