<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:667101359;
        mso-list-type:hybrid;
        mso-list-template-ids:-1747937194 134807569 134807577 134807579 134807567 134807577 134807579 134807567 134807577 134807579;}
@list l0:level1
        {mso-level-text:"%1\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-GB link="#0563C1" vlink="#954F72"><div class=WordSection1><p class=MsoNormal>Hi,<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Last time we defined X3DField and X3DArrayField objects based on the abstract standard ISO/IEC 19775-1:2013. Today, we’ll extend to a specific field type, and we’ll also add SAI information from ISO/IEC 19775-2:2015.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Let’s start with a simple field, and build definitions for SFInt32 and MFInt32.<o:p></o:p></p><p class=MsoNormal>Reference: ISO/IEC 19775-1:2013, 5.3.7 SFInt32 and MFInt32 – <a href="http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/fieldsDef.html#SFInt32AndMFInt32">http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/fieldsDef.html#SFInt32AndMFInt32</a><o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>What additional characteristics are required for each of these field types, in addition to those that will be inherited from the base classes? Only one. The value. In  order to add these we are going to need a new data type. We’ll call it “int32”, to represent a 32-bit integer. We will have, therefore:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>SFInt32 : X3DField {<o:p></o:p></p><p class=MsoNormal>    int32 value;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>MFInt32 : X3DArrayField {<o:p></o:p></p><p class=MsoNormal>    int32 value[];<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Because MFInt32 requires storage for multiple values, which can be none, we specify an array type by using square brackets. Furthermore, we leave the size of the array unspecified by not including a number within the brackets. However, there is one final thing we have to handle. And that is the default value. The text tells us that the default value for an SFInt32 field is 0, while that for an MFInt32 field is the empty list. For the SFInt32 field we will represent the default value by adding the expression “=0” to the value definition. For the MFInt32 field we do not need any additional text, as we will assume that when any array is created it is, by default, an empty list unless otherwise specified. Therefore, our SFIn32 definition becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>SFInt32 : X3DField {<o:p></o:p></p><p class=MsoNormal>    int32 value = 0;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Now, let’s turn to the SAI. And start with the ISO/IEC 19775-2:2016 clause 5 Data type reference.<o:p></o:p></p><p class=MsoNormal>Reference: <a href="http://www.web3d.org/documents/specifications/19775-2/V3.3/Part02/dataRef.html">http://www.web3d.org/documents/specifications/19775-2/V3.3/Part02/dataRef.html</a><o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Clause 5.2 specifies thirty seven data type definitions. For our immediate requirement to add SAI capabilities to the object definitions we have made so far, we are going to need the following:<o:p></o:p></p><ol style='margin-top:0cm' start=1 type=1><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo1'>5.2.11 SAIFieldAccess. This “… defines the type of access that is permitted to a field.”<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo1'>5.2.13 SAIField. This “… represents an identifier for a particular field of a node.”<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo1'>5.2.14 SAIFieldName. This “… represents a name for a field.”<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo1'>5.2.15 SAIFieldType. This “… specifies the type of data a field represents.”<o:p></o:p></li><li class=MsoListParagraph style='margin-left:0cm;mso-list:l0 level1 lfo1'>5.2.16 SAIFieldValue. This “… represents the value to be set or to be returned of an SAIFieldType in language specific terms.”<o:p></o:p></li></ol><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>What about primitive data types? We can see that there is an  SAIBoolean (clause 5.2.2) and an SAIString (clause 5.2.34). There is no data type corresponding to integers, floats or doubles. Let’s flag that.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><b>Problem 3</b>: The SAI does not define data types for primitives such as integers, floats, or doubles.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>To use these in our object model we either a) need to map the SAI data types to the types we use, or b) just use these types directly. Let’s try to do the latter, as we want the object model to be language independent, and we don’t want to introduce another mapping if we don’t need to.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Now we can look at the field service requirements, described in ISO/IEC 19775-2:2015 clause 6.7 Field services.<o:p></o:p></p><p class=MsoNormal>Reference: <a href="http://www.web3d.org/documents/specifications/19775-2/V3.3/Part02/servRef.html#FieldServices">http://www.web3d.org/documents/specifications/19775-2/V3.3/Part02/servRef.html#FieldServices</a><o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>We’ll work through these one at a time. The first is at clause 6.7.2 getAccessType. Because this introduces some new concepts, we’ll go through each line of the definition.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The first line is parameters, and for this function SAIField and SAINode are specified. We need to remember that we are defining an interface for fields. These are not permitted to exist outside of nodes. And how is a field reference obtained? By querying a node. So having a field reference implies the node reference, and we don’t need to add it into our interface.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The second line is the return type, SAIFieldAccess. But looking at our previous definition for X3DField, we defined an enumeration called AccessType. Now we can see that we should rename this enumeration to SAIFieldAccess. Therefore, this enumeration becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>enum SAIFieldAccess {<o:p></o:p></p><p class=MsoNormal>    initializeOnly,<o:p></o:p></p><p class=MsoNormal>    inputOnly,<o:p></o:p></p><p class=MsoNormal>    outputOnly,<o:p></o:p></p><p class=MsoNormal>    inputOutput<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>And our definition of X3DField is updated to:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum Type type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    string name;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The third line of the service definition specifies errors. It lists two, in addition to the one specified in the second paragraph in clause 6.7.1 Introduction. Therefore there are three errors, namely SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, and SAI_DISPOSED.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The remaining three lines deal with events, whether it is buffered, and whether it is only available to an external interface. None of these are of immediate concern.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Now that we have reviewed the service definition, we are in a position to define a method for getAccessType. Where shall we put it? Since this service is one that applies to every field, irrespective of type.  Therefore, it can be added to the X3DField definition, where it will be inherited by all fields. Thus, the X3DField object definition becomes as follows:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum Type type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    string name;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    enum SAIFieldAccess getAccessType (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>This definition introduces the “void” argument, which we define to mean that there are no arguments. It also introduces the term “throws” followed by an listing of all the permitted errors that may arise.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Now that we have the principles established we can repeat the same steps for the getType service, defined at 6.7.3 getType. We see that there is the data type SAIFieldType, that we need to use to replace our previous enumeration Type. This enumeration therefore becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>enum SAIFieldType {<o:p></o:p></p><p class=MsoNormal>    SFBool,<o:p></o:p></p><p class=MsoNormal>    MFBool,<o:p></o:p></p><p class=MsoNormal>    SFColor,<o:p></o:p></p><p class=MsoNormal>   …<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>And, again, we need to add this service to the X3DField definition, modifying the “type” characteristic too. The updated X3DField definition becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    string name;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    enum SAIFieldAccess getAccessType (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType getType (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Now we look at the getName service, specified at 6.7.4 getName. We note that there is a data type SAIFieldName. So we can use that to replace the previous “string” data type. The X3DField definition therefore becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName name;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    enum SAIFieldAccess getAccessType (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType getType (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName getName (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Moving on, we get to the getValue service, defined at 6.7.5 getValue. The data type of the value, or values, that are stored is dependent on the type of field. Therefore, this service will need to be defined in the individual field types, and not in the abstract X3DField. We’ll do it first for the SFInt32 field. Note that we can’t simply use SAIFieldValue. As explained in clause 5.2.15 this needs be mapped to different types, depending on the field type. We also need to do this mapping. For us, the data type for SAIFieldValue when the field type is SFInt32 or MFInt32 is int32. Therefore we need to define this mapping table, as we have it so far:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>SAIFieldValue mapping:<o:p></o:p></p><p class=MsoNormal>SFInt32/MFInt32 int32<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>We now add this service to our SFInt32 definition, and get:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>SFInt32 : X3DField {<o:p></o:p></p><p class=MsoNormal>    int32 value = 0;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    int32 getValue (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>And what about our MFInt32 definition. The text in the last paragraph states that “All field types shall support the option to return a single value from multi-valued arrays.”. So we need a separate function for that. We’ll define a function get1Value. It will have a single argument, representing the index into the array of the value to be returned. Furthermore, we need an additional error, in case the index is not within the bounds of the array size. When we look at the list of error types in clause 5.3, there isn’t a suitable one. We’ll flag that in a moment. Let’s define an additional error type SAI_INVALID_ARRAY_INDEX. In addition, we would also need a way to find out how many values there are in a multivalued field. So let’s define an additional method getNum which returns the number of elements in an array for a specific multivalued field. This last function should be added to the X3DFieldArray object, because it applies to all multivalued (MFxxxx) fields.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><b>Problem 4</b>: The SAI does not define an error type for an array index out of bounds.<o:p></o:p></p><p class=MsoNormal><b>Problem 5</b>: The SAI does not define specific services names for handling multivalued fields.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Therefore, our definitions for X3DArrayField and MFInt32 become:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DArrayField : X3DField {<o:p></o:p></p><p class=MsoNormal>    int getNum (void) throws throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>MFInt32 : X3DArrayField {<o:p></o:p></p><p class=MsoNormal>    int32 value[];<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    int32[] getValue (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    int32 get1Value (int index) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INVALID_ARRAY_INDEX, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Note that we have defined a new primitive type “int” to represent an integer, without making any reference to particular storage requirements.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Wow! That was a big one. But now we have the setValue service, defined at 6.7.6 setValue. Like getValue, this needs to be added to the specific field types, as well as setting individual values for multivalued fields. And for multivalued fields, there are additional requirements, specified in the last paragraph, to provide services to “… append and remove items from the existing field.”. In addition, we might also want a service to insert a new item, or remove all of the items in a multivalued field. Applying these to our existing definitions, we now get:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>SFInt32 : X3DField {<o:p></o:p></p><p class=MsoNormal>    int32 value = 0;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    int32 getValue (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void setValue (int32 newValue) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_IMPORTED_NODE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DArrayField : X3DField {<o:p></o:p></p><p class=MsoNormal>    int getNum (void) throws throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void removeAllValues (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_IMPORTED_NODE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void removeValue (int index) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_IMPORTED_NODE, SAI_INVALID_ARRAY_INDEX, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>MFInt32 : X3DArrayField {<o:p></o:p></p><p class=MsoNormal>    int32 value[];<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    int32[] getValue (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    int32 get1Value (int index) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INVALID_ARRAY_INDEX, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void appendValue (int32 newValue) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_IMPORTED_NODE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void insertValue (int index, int32 newValue) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INVALID_ARRAY_INDEX, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void setValue (int32 newValue[]) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_IMPORTED_NODE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void set1Value (int index, int32 newValue) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INVALID_ARRAY_INDEX, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Two more to go. The next service is registerFieldInterest, defined at 6.7.7 registerFieldInterest. We can see from Table 6.14 that there are two action types, namely AddInterest, and RemoveInterest. So we will define two methods in our interface for these. Furthermore, for the time being, we will use the parameter SAIRequester without further definition, and get back to that later in this series of steps. Both of these actions apply to every field, so need to be added to the X3DField class. So this becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName name;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    enum SAIFieldAccess getAccessType (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType getType (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName getName (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void addInterest (SAIRequester requester) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INSUFFICIENT_CAPABILITIES, SAI_NODE_IN_USE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void removeInterest (SAIRequester requester) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INSUFFICIENT_CAPABILITIES, SAI_NODE_IN_USE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>And finally, the last service is dispose, specified at clause 6.7.8 dispose. Again, it applies to every field, and needs to go into X3DField. So this finally becomes:<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>X3DField {<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType type;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldAccess accessType;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName name;<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>    enum SAIFieldAccess getAccessType (void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    enum SAIFieldType getType (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    SAIFieldName getName (void) throws SAI_CONNECTION_ERROR, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void addInterest (SAIRequester requester) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INSUFFICIENT_CAPABILITIES, SAI_NODE_IN_USE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void removeInterest (SAIRequester requester) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING, SAI_INVALID_ACCESS_TYPE, SAI_INSUFFICIENT_CAPABILITIES, SAI_NODE_IN_USE, SAI_DISPOSED;<o:p></o:p></p><p class=MsoNormal>    void dispose void) throws SAI_CONNECTION_ERROR, SAI_INVALID_OPERATION_TIMING;<o:p></o:p></p><p class=MsoNormal>};<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>And were done for this step. It might have been long, but we’ve done enough now to be able to move on to look at X3DNode next time.<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>All the best,<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Roy<o:p></o:p></p><p class=MsoNormal><o:p> </o:p></p></div></body></html>