[x3d-public] Action Needed: Need for acceptableStatements (or types)forchildren fields in X3DObject Model

John Carlson yottzumm at gmail.com
Sat Jul 29 18:42:19 PDT 2017


I also question whether all ConcreteNodes should be X3DChildNodes.  I doubt it.  What do you think?  If I take it out, what will break?  Frankly, I just threw X3DChildNode in there hoping it would fix something that was broken.  A more principled approach would be better—get the whole inheritance hierarchy into OM4X3D.

I will soon remove all references to X3DChildNode in my code and continue testing.  We will see what happens.

John



Sent from Mail for Windows 10

From: John Carlson
Sent: Saturday, July 29, 2017 9:11 PM
To: Don Brutzman; Roy Walmsley
Cc: X3D Graphics public mailing list
Subject: RE: Action Needed: Need for acceptableStatements (or types)forchildren fields in X3DObject Model


Specifically, I have this code in my JSON schema generator.  Previously, I uncommented the last line. The previous red is currently in question and will likely follow the rules of the comment. The yellow was added to “fix” OM4X3D, and is possibly incorrect (do you have something better?), but these are areas that may need to be addressed in OM4X3D. The True/False is a flag to determine whether something has IS or not—this should probably appear in OM4X3D as well.

Frankly, right now, it seems like ContentModels are fairly opaque in OM4X3D.

ants = soup.iter("AbstractNodeType")
for ant in ants:
    classes[ant.get('name')] = ClassPrinter(ant, {}, True)

classes["X3DConcreteNode"] = ClassPrinter("X3DConcreteNode", {}, True)
classes["X3DConcreteStatement"] = ClassPrinter("X3DConcreteStatement", {}, False)

aots = soup.iter("AbstractObjectType")
for aot in aots:
    classes[aot.get('name')] = ClassPrinter(aot, {}, False)

cns = soup.iter("ConcreteNode")
for cn in cns:
    classes[cn.get('name')] = ClassPrinter(cn, { "X3DConcreteNode" : 1, "X3DChildNode" : 1 }, True)
    classes["X3DConcreteNode"].children[cn.get("name")] = cn.get("name")
    classes["X3DChildNode"].children[cn.get("name")] = cn.get("name")

sts = soup.iter("Statement")
for st in sts:
    classes[st.get('name')] = ClassPrinter(st, { "X3DConcreteStatement" : 1, "X3DChildNode" : 1 }, False)
    classes["X3DConcreteStatement"].children[st.get("name")] = st.get("name")
    # classes["X3DChildNode"].children[st.get("name")] = st.get("name")
====================================================================================================
The following appear currently as X3DConcreteStatements in X3DJSAIL:

./jsail/Core/CommentsBlock.java
./jsail/Core/componentObject.java
./jsail/Core/connectObject.java
./jsail/Core/ExternProtoDeclareObject.java
./jsail/Core/fieldObject.java
./jsail/Core/fieldValueObject.java
./jsail/Core/headObject.java
./jsail/Core/ISObject.java
./jsail/Core/metaObject.java
./jsail/Core/ProtoBodyObject.java
./jsail/Core/ProtoDeclareObject.java
./jsail/Core/ProtoInterfaceObject.java
./jsail/Core/ROUTEObject.java
./jsail/Core/SceneObject.java
./jsail/Core/unitObject.java
./jsail/Core/X3DObject.java
./jsail/Networking/EXPORTObject.java
./jsail/Networking/IMPORTObject.java
./jsail/X3DConcreteStatement.java

And of those, these, at first glimpse, appear to be X3DChildNode:

$ find . -type f|xargs grep ConcreteStatement|grep X3DChildNode|awk -F: '{ print $1; }'
./jsail/Core/CommentsBlock.java
./jsail/Core/ExternProtoDeclareObject.java
./jsail/Core/ProtoDeclareObject.java
./jsail/Core/ROUTEObject.java
./jsail/Networking/EXPORTObject.java
./jsail/Networking/IMPORTObject.java

It is fairly obvious that I should not choose X3DChildNode as a parent of all Statements.   So I need a way in the X3D Object Model to distinguish X3DChildNodes from ordinary X3DConcreteStatements.

Looking at ROUTE in OM4X3D, I see no inheritance up to X3DChildNode:

      <Statement name="ROUTE">
         <InterfaceDefinition specificationUrl="http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/concepts.html#ModifyingObjectsRoutes"
                              appinfo="ROUTE connects output fields of event-producing nodes to input fields of event-consuming nodes.">
            <componentInfo name="Core" level="1"/>
            <field type="SFString"
                   accessType="inputOutput"
                   name="fromField"
                   use="required"/>
            <field type="SFString"
                   accessType="inputOutput"
                   name="fromNode"
                   use="required"/>
            <field type="SFString"
                   accessType="inputOutput"
                   name="toField"
                   use="required"/>
            <field type="SFString"
                   accessType="inputOutput"
                   name="toNode"
                   use="required"/>
         </InterfaceDefinition>
      </Statement>

So adding inheritance to X3DChildNode for the 5-6 statements in OM4X3D would also be an acceptable way of handling the issue.  Since X3DChildNode is already an acceptableNodeType, then my code would work.  I can obviously add an exception for the 5-6 statements, but wouldn’t that be defeating the purpose of the OM4X3D?

The problem I was having was that too many statements were being added as children, so I had to remove X3DChildNode as a parent for all statements. This left the 5-6 statements out in the cold.

Please help,

John

Sent from Mail for Windows 10

From: Don Brutzman
Sent: Saturday, July 29, 2017 6:13 PM
To: John Carlson; Roy Walmsley
Cc: X3D Graphics public mailing list
Subject: Re: Action Needed: Need for acceptableStatements (or types) forchildren fields in X3DObject Model

Thanks for the close scrutiny of OM4X3D and autogeneration/testing of JSON Schema, John.

BLUF recommendation: suggest you use current design patterns in existing X3D JSON Schema and we continue refining and improving everything together.  In this way, multiple X3D validation designs remain coherent and consistent while refining/evolving.  It is much much easier to compare to gain insight, and then incrementally improve matching approaches, than it is to reconcile divergent approaches.

Detailed analysis follows.

Sounds like you are using Object Model for X3D (OM4X3D) available at

                http://www.web3d.org/specifications/X3DObjectModel-3.3.xml

The content model for contained nodes and statements is generated from the content model for X3D XML Schema, and matches both XML Schema and DTD.

                http://www.web3d.org/specifications/x3d-3.3.xsd
                http://www.web3d.org/specifications/X3dSchemaDocumentation3.3.html

                http://www.web3d.org/specifications/x3d-3.3.dtd
                http://www.web3d.org/specifications/X3dDoctypeDocumentation3.3.html

Example excerpt follows:

<AbstractNodeType name="X3DGroupingNode">
    <InterfaceDefinition specificationUrl="http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/group.html#X3DGroupingNode"
                                                                                                appinfo="Grouping nodes can contain other nodes as children, thus making up the backbone of a scene graph.">
                  <componentInfo name="Grouping" level="1"/>
                  <Inheritance baseType="X3DChildNode"/>
                  <AdditionalInheritance baseType="X3DBoundedObject"/>
                  <field type="MFNode"
                                                accessType="inputOnly"
                                                name="addChildren"
                                                acceptableNodeTypes="X3DChildNode">
                                <componentInfo name="Grouping" level="2"/>
                  </field>
                  <field type="SFVec3f"
                                                accessType="initializeOnly"
                                                name="bboxCenter"
                                                default="0 0 0"/>
                  <field type="SFVec3f"
                                                accessType="initializeOnly"
                                                name="bboxSize"
                                                default="-1 -1 -1"
                                                baseType="boundingBoxSizeType"/>
                  <field type="MFNode"
                                                accessType="inputOutput"
                                                name="children"
                                                acceptableNodeTypes="X3DChildNode"/>
                  <field type="SFNode"
                                                accessType="inputOutput"
                                                name="metadata"
                                                default="NULL"
                                                acceptableNodeTypes="X3DMetadataObject"
                                                inheritedFrom="X3DNode"/>
                  <field type="MFNode"
                                                accessType="inputOnly"
                                                name="removeChildren"
                                                acceptableNodeTypes="X3DChildNode">
                                <componentInfo name="Grouping" level="2"/>
                  </field>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="DEF"
                                                inheritedFrom="DEF_USE"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="USE"
                                                inheritedFrom="DEF_USE"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="class"
                                                inheritedFrom="globalAttributes"/>
                  <ContentModel>
                                <GroupContentModel name="ChildContentModel" minOccurs="0" maxOccurs="unbounded"/>
                                <GroupContentModel name="ChildContentModelCore" minOccurs="0"/>
                  </ContentModel>
    </InterfaceDefinition>
</AbstractNodeType>

Here is a variant example which includes both primary GroupContentModel and then specificNodeContentModel  entries:

<ConcreteNode name="CADFace">
    <InterfaceDefinition specificationUrl="http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/components/CADGeometry.html#CADFace">
                  <componentInfo name="CADGeometry" level="2"/>
                  <Inheritance baseType="X3DProductStructureChildNode"/>
                  <AdditionalInheritance baseType="X3DBoundedObject"/>
                  <field type="SFVec3f"
                                                accessType="initializeOnly"
                                                name="bboxCenter"
                                                default="0 0 0"/>
                  <field type="SFVec3f"
                                                accessType="initializeOnly"
                                                name="bboxSize"
                                                default="-1 -1 -1"
                                                baseType="boundingBoxSizeType"/>
                  <field type="SFNode"
                                                accessType="inputOutput"
                                                name="metadata"
                                                default="NULL"
                                                acceptableNodeTypes="X3DMetadataObject"
                                                inheritedFrom="X3DNode"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="name"
                                                inheritedFrom="X3DProductStructureChildNode"/>
                  <field type="SFNode"
                                                accessType="inputOutput"
                                                name="shape"
                                                default="NULL"
                                                acceptableNodeTypes="Shape|LOD|Transform"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="DEF"
                                                inheritedFrom="DEF_USE"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="USE"
                                                inheritedFrom="DEF_USE"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="class"
                                                inheritedFrom="globalAttributes"/>
                  <containerFieldDefault name="children"/>
                  <ContentModel>
                                <GroupContentModel name="ChildContentModelCore" minOccurs="0"/>
                                <NodeContentModel name="Shape"/>
                                <NodeContentModel name="LOD"/>
                                <NodeContentModel name="Transform"/>
                                <NodeContentModel name="ProtoInstance"/>
                  </ContentModel>
    </InterfaceDefinition>
</ConcreteNode>

Here is a particular statement, ROUTE:

<Statement name="ROUTE">
    <InterfaceDefinition specificationUrl="http://www.web3d.org/documents/specifications/19775-1/V3.3/Part01/concepts.html#ModifyingObjectsRoutes"
                                                                                                appinfo="ROUTE connects output fields of event-producing nodes to input fields of event-consuming nodes.">
                  <componentInfo name="Core" level="1"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="fromField"
                                                use="required"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="fromNode"
                                                use="required"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="toField"
                                                use="required"/>
                  <field type="SFString"
                                                accessType="inputOutput"
                                                name="toNode"
                                                use="required"/>
    </InterfaceDefinition>
</Statement>

However "ROUTE" does not appear elsewhere in OM4X3D.  Its presence as a legal child node of X3DGroupingNode is implicit and can only be inferred by looking at ChildContentModel in X3D XML Schema.

As you have discovered, this appears to be an omission in the OMX3D definitions.

We certainly do want to keep everything consistent, and so precise treatment to make such a relationship explicit in OM4X3D will require further scrutiny of these design patterns, quite possibly according to the approach that you suggest.  Since the X3D content model is pretty involved, and since we are working across multiple encodings and programming languages, it is good to be careful and deliberate about these things.

Of related interest is to look at how X3DJSAIL handles this relationship by using class (rather than interface) hierarchy:
=================================================================
http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/Core/ROUTEObject.html

org.web3d.x3d.jsail.Core
Class ROUTEObject
     java.lang.Object
         org.web3d.x3d.jsail.X3DConcreteElement
             org.web3d.x3d.jsail.X3DConcreteStatement
                 org.web3d.x3d.jsail.Core.ROUTEObject

     All Implemented Interfaces:
         X3DChildNode, X3DNode
=================================================================

Note that since ROUTEObject implements X3DChildNode, it can appear within any X3D

First, it maintains the X3D interfaces from the X3D Abstract Specification (e.g. X3DChildNode, X3DNode) separate from the object hierarchy.

Second, since the abstract specification does not list interfaces for statements (root cause of this current design gap), it creates
Class X3DConcreteElement which has two concrete subclasses: X3DConcreteNode and X3DConcreteStatement.

=================================================================
http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/X3DConcreteElement.html
http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/package-tree.html

org.web3d.x3d.jsail
Class X3DConcreteElement
     java.lang.Object
         org.web3d.x3d.jsail.X3DConcreteElement

     Direct Known Subclasses:
         X3DConcreteNode, X3DConcreteStatement
=================================================================

After considering and trying a number of approaches, I left the X3D specification interfaces verbatim/unchanged and handled the necessary additions via this class/subclass approach.  It achieves the same content model as X3D specification and XML schema with the addition of strong typing.  Strong typing of elements (i.e. nodes or statements) means that creation of a valid scene graph is easily allowed (indeed with choices prompted by IDE).  Meanwhile, creation of an invalid scene graph is not permitted since that would violate strong typing requirements and thus fail compilation.

Next... Looking closely at Roy's manually created X3D JSON schema is particularly important for what you are doing.  Some excerpts:
=================================================================
http://www.web3d.org/specifications/x3d-3.3-JSONSchema.json
http://www.web3d.org/specifications/X3dJsonSchemaDocumentation3.3.html

JSON Schema definition, Group documentation:
http://www.web3d.org/specifications/X3dJsonSchemaDocumentation3.3/x3d-3.3-JSONSchema.html#Link54

"Group": {
     "type": "object",
     "properties": {
         "@DEF": {
             "type": "string"
         },
         "@USE": {
             "type": "string"
         },
         "IS": {
             "$ref": "#/definitions/IS"
         },
         "@bboxCenter": {
             "type": "array",
             "minItems": 3,
             "maxItems": 3,
             "items": {
                 "type": "number",
                 "default": 0
             }
         },
         "@bboxSize": {
             "$ref": "#/definitions/@bboxSize"
         },
         "-children": {
             "$ref": "#/definitions/-children"
         },
         "-metadata": {
             "$ref": "#/definitions/-metadata"
         }
     },
     "additionalProperties": false
}

=================================================================
JSON Schema definition, CADFace documentation:
                http://www.web3d.org/specifications/X3dJsonSchemaDocumentation3.3/x3d-3.3-JSONSchema.html#Link12

"CADFace": {
                "type": "object",
                "properties": {
                                "@DEF": {
                                                "type": "string"
                                },
                                "@USE": {
                                                "type": "string"
                                },
                                "IS": {
                                                "$ref": "#/definitions/IS"
                                },
                                "@bboxCenter": {
                                                "type": "array",
                                                "minItems": 3,
                                                "maxItems": 3,
                                                "items": {
                                                                "type": "number",
                                                                "default": 0
                                                }
                                },
                                "@bboxSize": {
                                                "$ref": "#/definitions/@bboxSize"
                                },
                                "@name": {
                                                "type": "string"
                                },
                                "-metadata": {
                                                "$ref": "#/definitions/-metadata"
                                },
                                "-shape": {
                                                "type": "object",
                                                "properties": {
                                                                "LOD": {
                                                                                "$ref": "#/definitions/LOD"
                                                                },
                                                                "Shape": {
                                                                                "$ref": "#/definitions/Shape"
                                                                },
                                                                "Transform": {
                                                                                "$ref": "#/definitions/Transform"
                                                                },
                                                                "ProtoInstance": {
                                                                                "$ref": "#/definitions/ProtoInstance"
                                                                }
                                                },
                                                "additionalProperties": false
                                },
                                "-children": {
                                                "$ref": "#/definitions/-commentRoute"
                                }
                },
                "additionalProperties": false
},

=================================================================
JSON Schema definition -children
http://www.web3d.org/specifications/X3dJsonSchemaDocumentation3.3/x3d-3.3-JSONSchema.html#Link107

(scroll down to "source code)

"-children": {
     "description": "MF X3DChildNode content",
     "type": "array",
     "minItems": 1,
     "items": {
         "type": "object",
         "properties": {
             "#comment": {
                 "type": "string"
             },
             "ProtoInstance": {
                 "$ref": "#/definitions/ProtoInstance"
             },
             "Anchor": {
                 "$ref": "#/definitions/Anchor"
             },
             "AudioClip": {
                 "$ref": "#/definitions/AudioClip"
             },
             "Background": {
                 "$ref": "#/definitions/Background"
             },

[... many nodes skipped ...]
             "VolumePickSensor": {
                 "$ref": "#/definitions/VolumePickSensor"
             },
             "WorldInfo": {
                 "$ref": "#/definitions/WorldInfo"
             },
             "ROUTE": {
                 "$ref": "#/definitions/ROUTE"
             },
             "ProtoDeclare": {
                 "$ref": "#/definitions/ProtoDeclare"
             },
             "ExternProtoDeclare": {
                 "$ref": "#/definitions/ExternProtoDeclare"
             },
             "IMPORT": {
                 "$ref": "#/definitions/IMPORT"
             },
             "EXPORT": {
                 "$ref": "#/definitions/EXPORT"
             }
         },
         "additionalProperties": false
     }
}
=================================================================

Point worth noting in preceding: we gave comment and ROUTE the prefix key "-children".  I think we should take a similar approach for IMPORT and EXPORT if they appear within nodes that are not X3DGroupingNode.

So, hope this helps, please advise what you think.

v/r Don


On 7/29/2017 1:11 PM, John Carlson wrote:
> Are we assuming that can acceptableNodeTypes in the object model will allow for acceptableStatements?   I'd like to see action on this in the object model (put the statements or abstract types for statements into acceptableNodeTypes) so I can continue with autogeneration of the JSON schema.
> 
> On Jul 20, 2017 1:22 PM, "John Carlson" <yottzumm at gmail.com <mailto:yottzumm at gmail.com>> wrote:
>     __ __
> 
>     I believe we need acceptableStatements to restrict acceptable statements for children fields in the X3D Object Model.  If it’s ProtoInstance we have a acceptable statements which are comments. If no children field is found, then we have -commentRoute in JSON schema (temporarily now -childrenStatements). However if there are children, there’s no way to specify which statements are allowed. Previously, I tacked X3DChildNode above the statement inheritance hierarchy in my schema generator, which was wrong.
> 
>     __ __
> 
>     Do we need to extend this extra children field to other nodes so they can accept statements? And then just don’t support any acceptableNodeTypes for those children?____
> 
>     __ __
> 
>     Can we separate nodes and statements into separate children arrays in X3DJSON?____
> 
>     __ __
> 
>     Things to think about.____


all the best, Don
-- 
Don Brutzman  Naval Postgraduate School, Code USW/Br       brutzman at nps.edu
Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA   +1.831.656.2149
X3D graphics, virtual worlds, navy robotics http://faculty.nps.edu/brutzman


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://web3d.org/pipermail/x3d-public_web3d.org/attachments/20170729/59de62aa/attachment-0001.html>


More information about the x3d-public mailing list