<html 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=utf-8"><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:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal>Transform().setIS(IS()).addChild(Shape())</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>is the simplest example that throws an error. Simpler examples succeed.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I didn’t run the code with the nested transform.  I am not even sure it’s possible.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>So if were’ not addressing addChild, then I think we must address setIS().</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>addChild could throw an exception in X3DConcreteNode.   IDK.   Just woke up pretty much.  I am pretty much ready to fall asleep again.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I have been leaving the Java solutions to you, because XSLT is painful.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I don’t believe the cast or wrap of the outer object is a good solution, because I think it may postpone the issue (we may have to cast for each set method, which I think would lead more code than the other “verbose” serializer).  But the idea seems sound, just verbose.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I am not addressing the setDEF problem because string wrappers solve it.  I am trying to address the problem that hasn’t been solved.  We can go back to solving more easier to address problems once the harder problems are solved.  If you think it’s the same pattern, I’m willing to put some effort in.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Addressing what’s returned from a JavaMethod in pyjnius is a good plan.   Great idea!</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I am suspecting we could do something in this code in jnius_export_class.pxi, but it’s not compatible with most Java, we’d probably have to put some code with an extra predicate, something like and method_name starts with “set”</p><p class=MsoNormal>        elif r == 'L':</p><p class=MsoNormal>            with nogil:</p><p class=MsoNormal>                j_object = j_env[0].CallObjectMethodA(</p><p class=MsoNormal>                        j_env, j_self, self.j_method, j_args)</p><p class=MsoNormal>            check_exception(j_env)</p><p class=MsoNormal>            if j_object != NULL:</p><p class=MsoNormal>                ret = convert_jobject_to_python(</p><p class=MsoNormal>                        j_env, self.definition_return, j_object)</p><p class=MsoNormal>                j_env[0].DeleteLocalRef(j_env, j_object)</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>and set ret to self, I guess.  Not really that sure.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>If you think this is a good thing to pursue, I will look into it</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I will wait until you have the word on setDEF.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Thanks,</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>John</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Sent from <a href="https://go.microsoft.com/fwlink/?LinkId=550986">Mail</a> for Windows 10</p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:brutzman@nps.edu">Brutzman, Donald (Don) (CIV)</a><br><b>Sent: </b>Thursday, May 16, 2019 5:38 AM<br><b>To: </b><a href="mailto:yottzumm@gmail.com">John Carlson</a>; <a href="mailto:x3d-public@web3d.org">X3D Graphics public mailing list</a>; <a href="mailto:aono@tut.jp">aono@tut.jp</a><br><b>Subject: </b>Re: Simple example of X3DConcreteNode/addChild problem</p></div><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Hi John.  Thanks for continued sleuthing.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>1. Chasing addChild() is probably not a good path forward however.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>The addChild() method cannot be added to X3DConcreteNode because then any X3D node would be able to add a child node.  That obviously breaks the parent-child hierarchy restrictions of XxD scene graph.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>As an example: all nodes can add a single MetadataFloat child, and (as you note) IS node (for IS/connect links within a ProtoBody).  However nodes like Material cannot add any other child nodes, since those are not part of the allowed X3D scene graph.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>This strictness is part of the fundamental value of X3D structural validity.  It is similarly enforced by validation techniques such as XML Schema, JSON schema, XML DTD, XML Schematron, and X3DUOM.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I suspect that the error you are seeing from</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>                Transform(Transform().setIS(IS())).addChild(Shape())</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>matching (commented) legal subgraph</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>   <Transform></p><p class=MsoNormal>     <Transform></p><p class=MsoNormal>       <IS><!-- needs a connect statement--></IS></p><p class=MsoNormal>       <Shape/></p><p class=MsoNormal>     </Transform></p><p class=MsoNormal>   </Transform></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>is actually quite similar in nature to the other flawed (misdirecting) pyjnius errors we've been seeing with ViewpointObject, most recently re-diagnosed as a setDEF() problem.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Any time pyjnius says that it has a problem with X3DConcreteNode there is a problem in the matching of the .py python source to underlying X3DJSAIL classes.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Give me a chance to go further on the setDEF() problem.  Once that is resolvable, it will be similarly applied to USE and IS since all three are part of X3DConcreteNode.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>http://www.web3d.org/specifications/java/javadoc/org/web3d/x3d/jsail/X3DConcreteNode.html</p><p class=MsoNormal>"Abstract parent class for concrete X3D nodes, containing common methods and member variables."</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Am currently looking at two potential paths for solution:</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>a. possibly omit DEF, USE from org.web3d.x3d.sai.Navigation.Viewpoint interface (still questionable)</p><p class=MsoNormal>b. get pyjnius to return class current object when returning from methods, rather than a superclass or interface (root cause of problem)</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Summary: don't worry about "addChild()" since the root problem is elsewhere.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>2. @Override annotation will never "work" because it has no action.  It is a Java compiler-related note that helps warnings ensure that programmer Object-oriented design intentions are met.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>3. Great to hear that you are making some strides with Jupyter.  Recommend using an even-simpler example that current works, perhaps HelloTriangle.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>http://x3dgraphics.com/examples/X3dForWebAuthors/Chapter01TechnicalOverview/HelloTriangleIndex.html</p><p class=MsoNormal>http://x3dgraphics.com/examples/X3dForWebAuthors/Chapter01TechnicalOverview/HelloTriangle.x3d</p><p class=MsoNormal>http://x3dgraphics.com/examples/X3dForWebAuthors/Chapter01TechnicalOverview/HelloTriangle.java</p><p class=MsoNormal>http://x3dgraphics.com/examples/X3dForWebAuthors/Chapter01TechnicalOverview/HelloTriangle.py</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>p.s. looks like some of the online .py files didn't get updated, will recheck the build process.  Example attached.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>On 5/14/2019 9:33 AM, John Carlson wrote:</p><p class=MsoNormal>> Example of error generated below.  (minimal amount of code) Jupyter export attached.  I hope you can address the issue sometime with X3DJSAIL.  My best guess is that pyjnius is going through getSuperclass() and finding the abstract classes’ method setIS().  We can try deleting getSuperclass call in pyjnius if you think it’s appropriate.</p><p class=MsoNormal>> </p><p class=MsoNormal>> My suggestion is to delete setIS from X3DConcreteNode.java or implement addChild in X3DConcreteNode.java, which may just cascade the error.  I think deleting setIS might be preferable, but test both cases.   Consider a wrapping, like:</p><p class=MsoNormal>> </p><p class=MsoNormal>> Transform(Transform().setIS(IS())).addChild(Shape())  # hasn’t been tested, but ew.</p><p class=MsoNormal>> </p><p class=MsoNormal>> A jnius.cast would work similarly.  We can go with a cast if you like.  Please look into a cast to see what you prefer.  Also, try converting to Java.</p><p class=MsoNormal>> </p><p class=MsoNormal>> Now do you see where the abstract class is coming from?  Do you agree on what’s introducing the abstract class (not me)?</p><p class=MsoNormal>> </p><p class=MsoNormal>> Good news is, I and Michael figured out how to run the code in Jupyter Lab (anaconda).  There are instructions online that work with the conda.bat command install jnius (see conda install on pyjnius website)  WooHoo! Highly recommended, but a bit stilted to start with.</p><p class=MsoNormal>> </p><p class=MsoNormal>> Code is back to you! Looking for changes to X3DConcreteNode.java.  I can make changes to the serializer if we decide wrapping or casting is appropriate.  I just think we’ll be wrapping the wrapping the wrapping.  It seems better to me to add or delete abstract methods.</p><p class=MsoNormal>> </p><p class=MsoNormal>> No, I don’t know why @Override didn’t work.</p><p class=MsoNormal>> </p><p class=MsoNormal>> # This code shows the error</p><p class=MsoNormal>> </p><p class=MsoNormal>> import jnius_config</p><p class=MsoNormal>> </p><p class=MsoNormal>> jnius_config.set_classpath('.', 'c:/x3d-code/www.web3d.org/x3d/stylesheets/java/jars/X3DJSAIL.3.3.full.jar')</p><p class=MsoNormal>> </p><p class=MsoNormal>> from jnius import autoclass</p><p class=MsoNormal>> </p><p class=MsoNormal>> Shape = autoclass('org.web3d.x3d.jsail.Shape.ShapeObject')</p><p class=MsoNormal>> </p><p class=MsoNormal>> Transform = autoclass('org.web3d.x3d.jsail.Grouping.TransformObject')</p><p class=MsoNormal>> </p><p class=MsoNormal>> IS = autoclass('org.web3d.x3d.jsail.Core.ISObject')</p><p class=MsoNormal>> </p><p class=MsoNormal>> Transform().setIS(IS()).addChild(Shape())</p><p class=MsoNormal>> </p><p class=MsoNormal>> *-------------------------------------------------------------------------*</p><p class=MsoNormal>> </p><p class=MsoNormal>> *AttributeError*                            Traceback (most recent call last)</p><p class=MsoNormal>> </p><p class=MsoNormal>> *<ipython-input-1-62dabff95a4e>*in <module></p><p class=MsoNormal>> </p><p class=MsoNormal>>        8</p><p class=MsoNormal>> </p><p class=MsoNormal>>        9</p><p class=MsoNormal>> </p><p class=MsoNormal>> *---> 10***Transform*().*setIS*(*IS*()).*addChild*(*Shape*())*</p><p class=MsoNormal>> </p><p class=MsoNormal>> *AttributeError*: 'org.web3d.x3d.jsail.X3DConcreteNode' object has no attribute 'addChild'</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>all the best, Don</p><p class=MsoNormal>-- </p><p class=MsoNormal>Don Brutzman  Naval Postgraduate School, Code USW/Br       brutzman@nps.edu</p><p class=MsoNormal>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA   +1.831.656.2149</p><p class=MsoNormal>X3D graphics, virtual worlds, navy robotics http://faculty.nps.edu/brutzman</p><p class=MsoNormal><o:p> </o:p></p></div></body></html>