[x3d-public] X3D Java SAI. Declarative style

Don Brutzman brutzman at nps.edu
Wed Jan 25 08:03:08 PST 2017


The X3D Java Scene Access Interface Library (X3DJSAIL) now has one more important utility method for grouping nodes, addChild(X3DChildNode newValue), that enables declarative-style pipelined method invocation.

This supports the primary X3DJSAIL design goals: make it easy for a Java programmer to build a valid  X3D scene graph, and make it hard to include any error.

This addition is an alternative to the specification addChildren() interface that can only return void and cannot be pipelined.  The implementation utilizes and exposes design patterns within the Java Collections package for common object operations.

Benefits previously described for this alternative Java programming style now appear to be available anywhere that a Java programmer is working on an X3D scene graph.

_Functional Programming in Java_ by Venkat Suramaniam https://pragprog.com/book/vsjava8/functional-programming-in-java
notes benefits such as
=================
- No messing around with mutable variables, avoiding side effects
- Less clutter, better clarity: retains our focus
- Less impedance: code closely trails the business intent
- Less error prone, easier to understand and maintain
- Hassle-free concurrency, telling the story declaratively
- Separation of concerns, delaying evaluation, improving testability
=================

Classical approaches of object declaration and line-by-line invocations are also available and can be intermixed as a programmer prefers.  This is demonstrated in the current example test program.
	http://www.web3d.org/specifications/java/X3dJavaSceneAuthoringInterface.html#Examples
	http://www.web3d.org/specifications/java/examples/HelloWorldProgram.java

HelloWorldProgram.java excerpt:
===================================
private void createDeclarativeShapeTests()
{
	String innerMaterialNodeDEF    = "DeclarativeMaterialExample";
	String innerMetadataStringName = "findThisNameValue";

	GroupObject declarativeGroup = new GroupObject("DeclarativeGroupExample")
		// addChild is singleton pipeline method, avoiding return-void restrictions of SAI addChildren interface
		.addChild(new ShapeObject()
			.setAppearance(new AppearanceObject()
				.setMaterial(new MaterialObject(innerMaterialNodeDEF)
					.setDiffuseColor(SFColorObject.LIGHTSEAGREEN)))
			.setGeometry(new ConeObject()
				.setHeight(0.1f).setBottomRadius(0.05f).setBottom(false))
			.setMetadata(new MetadataStringObject("FindableMetadataStringTest")
				.setName(innerMetadataStringName).setValue("test case")))
		.addComments("Test success: declarativeGroup.addChild() singleton pipeline method");

	scene.addComments("Test success: declarative statement createDeclarativeShapeTests()")
		 .addChild   (declarativeGroup) // addChild is pipeline method
		 .addComments(new CommentsBlock("Test success: declarative statement addChild()"));

	// Now check and report result: can we find inner node?
	CommentsBlock createDeclarativeShapeTestResults = new CommentsBlock();
	X3DConcreteElement nodeFoundByDEF = x3dModel.findNodeByDEF(innerMaterialNodeDEF);
	if  (nodeFoundByDEF != null)
		 createDeclarativeShapeTestResults.addComments("Test success: x3dModel.findNodeByDEF(" + innerMaterialNodeDEF + ") = " +
			nodeFoundByDEF.toStringX3D().trim());
	else createDeclarativeShapeTestResults.addComments("Test failure: x3dModel.findNodeByDEF(" + innerMaterialNodeDEF + ") = null");

	X3DConcreteElement nodeFoundByName = x3dModel.findElementByNameValue(innerMetadataStringName);
	if  (nodeFoundByName != null)
		 createDeclarativeShapeTestResults.addComments("Test success: x3dModel.findElementByNameValue(" + innerMetadataStringName + ") = " +
			nodeFoundByName.toStringX3D().trim());
	else createDeclarativeShapeTestResults.addComments("Test failure: x3dModel.findElementByNameValue(" + innerMetadataStringName + ") = null");
	scene.addChild(createDeclarativeShapeTestResults); // addChildren also works but is not pipelined
}
===================================

As described before, hidden inner classes can later be found via any conncected ancestor node (such as SceneObject) using

	 findNodeByDEF(String DEFvalue) and findElementByNameValue(String nameValue).

Design considerations: multiple identical DEFs in a scene will not validate, so findNodeByDEF() only returns the first-found object reference.  However multiple identical name attributes may be present (for example, when duplicate HAnimHumanoids are present, or every time when using ProtoDeclare/ExternProtodeclare with ProtoInstance.  Am considering further refinement of findElementByNameValue() method to better handle such cases, feedback will be welcome.

Existing scene-graph export capabilities include .x3d .x3dv .wrl .json .html X3DOM and Cobweb.  Given the apparent completeness of core functionality, upcoming work will add further capabilities such as exception logging, EXI compression, XML Security and other features.  Since X3DJSAIL is a library, discussion about adding further features and additional libraries like .ply/.stl export, 3D printing support, H-Anim utilities etc. jGeom for NURBS, OpenDIS, etc. will be welcome.

X3DJSAIL update deployed at

	http://www.web3d.org/specifications/java/X3dJavaSceneAuthoringInterface.html

Have fun with X3D Java!  8)

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



More information about the x3d-public mailing list