001package Torello.Browser.JsonAST;
002
003import Torello.JavaDoc.Annotations.LinkJavaSource;
004import Torello.JavaDoc.Annotations.JDHeaderBackgroundImg;
005
006import Torello.JSON.ReadJSON;
007
008import Torello.Java.ReadOnly.ReadOnlySet;
009import Torello.Java.ReadOnly.ReadOnlyTreeSet;
010
011import Torello.Browser.CDPTypes;
012
013import javax.json.JsonObject;
014import java.io.IOException;
015import java.util.Objects;
016
017
018/**
019 * Contains the data needed to represent a property, parameter or return value.
020 * <EMBED CLASS='external-html' DATA-FILE-ID=AST_TREES>
021 */
022@JDHeaderBackgroundImg(EmbedTagFileID="AST_NODES_JDHBI")
023public class PPR extends Entity implements java.io.Serializable
024{
025    // ********************************************************************************************
026    // ********************************************************************************************
027    // STATIC FINAL FIELDS
028    // ********************************************************************************************
029    // ********************************************************************************************
030
031
032    /** <EMBED CLASS='external-html' DATA-FILE-ID=SVUID> */
033    protected static final long serialVersionUID = 1;
034
035    /**
036     * The list of additional {@link JsonObject} properties that the parser should expect when
037     * parsing {@code PPR} objects from the JSON CDP specification files.
038     */
039    protected static final ReadOnlySet<String> PPR_JSON_PROPERTIES =
040        new ReadOnlyTreeSet<>(String::compareTo, "name", "$ref");
041
042
043    // ********************************************************************************************
044    // ********************************************************************************************
045    // Constant & Final Instance-Fields (Set by the Constructor)
046    // ********************************************************************************************
047    // ********************************************************************************************
048
049
050    /**
051     * This is a "Back Pointer" to the {@link TCE} (either a {@link TypeNode}, {@link CommandNode}
052     * or {@link EventNode}) that is the parent or owner of {@code 'this'} PPR instance.
053     */
054    public final TCE ownerTCE;
055
056    /**
057     * Expresses, explicitly, (without requiring an {@code 'instanceof'} operator), whether or not
058     * {@code 'this'} instance repesents a property, a parameter or a return-value.
059     * 
060     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.which>
061     */
062    public final WhichPPR which;
063
064    /**
065     * This field is declared {@code final}, and contains the raw-{@code String} value which is
066     * retrieved (during JSON parsing) from the {@code "$ref"} {@link JsonObject} property which
067     * defines {@code 'this' PPR} instance 
068     * 
069     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.ref>
070     */
071    public final String ref;
072
073    /**
074     * This {@code String} is declared {@code final}, and contains the raw-{@code String} value
075     * which is retrieved during the parsing of an {@code 'items'} {@link JsonObject} within this
076     * {@code PPR} definition.
077     * 
078     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.refArray>
079     */
080    public final String refArray;
081
082
083    // ********************************************************************************************
084    // ********************************************************************************************
085    // Non-Final Fields, set By the Linker
086    // ********************************************************************************************
087    // ********************************************************************************************
088
089
090    private TypeNode    reference       = null;
091    private TypeNode    referenceArray  = null;
092    private String      ctas            = null;
093    private byte        ctab            = 0;
094
095    /**
096     * Returns the value of the {@code private} field {@code 'reference'}; a field that represents
097     * the resolved target of a {@code '$ref'} property.
098     * 
099     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.reference>
100     */
101    public final TypeNode reference() { return reference; }
102
103    /**
104     * Returns the value of the {@code private} field {@code 'referenceArray'}; a field that
105     * represents the resolved target of a {@code '$ref'} property which was extracted from an
106     * {@code 'items'} object.
107     * 
108     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.referenceArray>
109     */
110    public final TypeNode referenceArray() { return referenceArray; }
111
112    /**
113     * Returns the value of the private field {@code 'ctas'}; a field that represents the
114     * "Computed Type as String" - the <B STYLE='color:red;'><I>Java Type of this PPR</I></B>, as a
115     * {@code java.lang.String}).
116     * 
117     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.CTAS>
118     * 
119     * @see CTAB
120     */
121    public final String CTAS() { return ctas; }
122
123    /**
124     * Returns the value of the private field {@code 'ctab'}; a field that represents the "Computed
125     * Type as Byte".
126     * 
127     * <EMBED CLASS='external-html' DATA-FILE-ID=PPR.CTAB>
128     * 
129     * @see CTAS
130     * @see CDPTypes 
131     */
132    public final byte CTAB() { return ctab; }
133
134
135    // ********************************************************************************************
136    // ********************************************************************************************
137    // Package-Private Setters; nethods not visible to callers from outside of Java-HTML
138    // ********************************************************************************************
139    // ********************************************************************************************
140
141
142    // It is important to realize that 'reference' and 'referenceArray' must be assigned first,
143    // if they are ever going to be assigned to anything other than null.
144
145    private static final String LINK_ERROR_MSG = 
146        "A value has already been assigned to the 'ctas' or 'ctab' fields.  These fields " +
147        "contain the 'Computed Type', and once they have been assigned, reassigning a value " +
148        "to field 'reference' or 'referenceArray' is not allowed.";
149
150    void setReference(final TypeNode reference)
151    {
152        // This is a "Space Age UnreachableError" Check.
153        if ((this.ctas != null) || (this.ctab != 0)) throw new LinkingStateError(LINK_ERROR_MSG);
154        this.reference = reference;
155    }
156
157    void setReferenceArray(final TypeNode referenceArray)
158    {
159        // This is a "Space Age UnreachableError" Check.
160        if ((this.ctas != null) || (this.ctab != 0)) throw new LinkingStateError(LINK_ERROR_MSG);
161        this.referenceArray = referenceArray;
162    }
163
164    void setCTAS(final String ctas)
165    {
166        if ((this.ctas != null) || (this.ctab != 0)) throw new LinkingStateError
167            ("'ctas' or 'ctab' have already been assigned.  They may not be reassigned.");
168
169        this.ctas = ctas;
170        this.ctab = CDPTypes.ctasToByte(ctas, reference != null, referenceArray != null);
171    }
172
173
174    // ********************************************************************************************
175    // ********************************************************************************************
176    // Constructor
177    // ********************************************************************************************
178    // ********************************************************************************************
179
180
181    PPR(
182            final TCE           ownerTCE,
183            final JsonObject    jo,
184            final WhichPPR      which,
185            final int           index
186        )
187    {
188        super(
189            ownerTCE.ownerDomain,
190            WhichEntity.ClassPPR,
191            jo,
192            index,
193            PPR_JSON_PROPERTIES
194        );
195
196        this.ownerTCE   = ownerTCE;
197        this.which      = which;
198
199        // getString(JsonObject jo, String propertyName, boolean isOptional, boolean throwOnNull)
200        this.ref = ReadJSON.getString(jo, "$ref", true, true);
201
202        if ((this.typeProp == TypeProp.ARRAY) && (this.arrItemsTypeProp == null))
203        {
204            // getJsonObject(jo, propertyName, boolean isOptional, boolean throwOnNull)
205            final JsonObject arrItemsProp = ReadJSON.getJsonObject(jo, "items", false, true);
206
207            // getString jo, propertyName, boolean isOptional, boolean throwOnNull)
208            this.refArray = ReadJSON.getString(arrItemsProp, "$ref", false, true);
209        }
210
211        else this.refArray = null;
212    }
213
214
215    // ********************************************************************************************
216    // ********************************************************************************************
217    // Cloneable, Comparable, Object
218    // ********************************************************************************************
219    // ********************************************************************************************
220
221
222    /** Returns a {@code String} representation of {@code 'this'} instance. */
223    @LinkJavaSource(handle="StringPPR")
224    public String toString()
225    { return StringPPR.get(this); }
226
227    /**
228     * Returns a brief (shorter than the {@link toString}a output)) {@code String} summary of
229     * {@code 'this'} instance.
230     */
231    public String toStringShort()
232    {
233        return
234            this.ownerDomain.ownerAPI.name + '.' +  // API-Name
235            this.ownerDomain.name + '.' +           // Domain-Name
236            this.ownerTCE.name + '.' +              // TCE-Name
237            this.name + ' ' +                       // PPR-Name
238            "[WhichTCE." + this.ownerTCE.which + ", WhichPPR." + this.which + ']';
239    }
240}