Hi Rob, > On 12 Jul 2018, at 01:22, rob.atkin...@surroundaustralia.com wrote: > > BTW - still trying to get my head around why sometimes a viewClass is used > and sometimes an instance of such a class - both seem to co-exist in EDG - > but whats the reason for using instances - and do they just behave like their > parent classes? and what if there are multiple? > > the properties of an instance do not shed much light on why they exist. You > previously pointed to classView as a way to invoke a service. the docs leave > me no wiser: > > " > _view The URI of a specific view to display (instance of ui:Element). > _viewClass The URI or qname of a user-defined view class (subclass of > ui:Elements) to display. All other arguments that match the declared > arguments of the view class will be passed into the view, e.g. > uispin?_viewClass=ex:MyView&name=Test will be comparable to <ex:MyView > arg:name="Test" />." > > is this explained in more detail elsewhere?
Not really, but it should be, so I started to write up some stuff. See below. Richard == SWP views are nested blank node structures == SWP views are written in XML: <ex:MyView arg:name="Test"/> But internally, this is treated not as XML but as a structure of nested blank nodes. The snippet above would be a blank node with rdf:type ex:MyView, and a property arg:name with value “Test”. In the case of XML with child elements, the root will still look as above, but there are further connected blank nodes for each child. An SWP developer rarely needs to know the details beyond that. == Associating SWP views with classes and resources == There are a number of ways how these blank node structures can be associated with classes and resources: 1. ui:view associates an SWP view with a resource (an instance). The view is supposed to render the resource. 2. ui:instanceView associates an SWP view with a class. The view is supposed to render instances of the class. The instance to render is passed to the executing view as variable ?this. ui:view and ui:instanceView are used to “dress up” domain models (a.k.a. domain ontologies) with presentation information that indicates how to display the entities in the model. 3. ui:prototype associates an SWP view with a class. The view is supposed to accept arguments, and render a response based on these arguments. The arguments are passed in as variables. The view itself does not need to be concerned with the question where the arguments come from and who provides them. Classes that have a ui:prototype become available for use as custom XML elements in other views. The ex:MyView example given earlier assumes that ex:MyView is itself a class that has a ui:prototype. When the SWP engine renders the view example, it would call the ui:prototype and pass in the argument ?name with value “Test”. It is worth noting that the instances of a class with a ui:prototype are typically blank nodes that are SWP views. So we can think of our <ex:MyView arg:name="Test"> example view as an instance of ex:MyView that fills in the required arguments. 4. ui:errorPrototype, ui:headIncludes, and a few other properties are typically used to associate helper views for specific purposes to class hierarchies that use ui:prototype. They usually do not contain business logic. ui:prototype and friends are used to package SWP views as reusable building blocks, and to develop full interactive web applications. == Rendering SWP views via the SWP servlet == The most important way to execute SWP views is the SWP servlet of TBL/EVN/EDG. When calling the servlet, the view to execute can be specified in a number of ways: 1. /tbl/swp?_view=xxx directly names the view to render. As stated above, SWP views are structures of nested blank nodes, so this would need to name the top-level blank node of the view. This option rarely needs to be used directly by developers, but is used internally when a part of a view needs to be rendered, e.g., with ui:loadable or ui:handle. 2. /tbl/swp?_resource=xxx names a resource to render. The SWP servlet will check if the resource has a ui:view property, and if so render that view. Or else, walk up the class hierarchy to find a ui:instanceView property, and render that with the resource bound to ?this. There are additional arguments to pick between multiple applicable views. This is also what the “Browser” tab in TBCME does. 3. /tbl/swp?_viewClass=xxx names a class whose ui:prototype to render. Any additional parameters to the HTTP request (e.g., ¶m1=yyy¶m2=zzz) will be passed in as arguments. In applications written in SWP, most pages are rendered in this way. It’s worth knowing that such calls actually create a new view on the fly, and render that view. So, ?_viewClass=ex:MyView&name=Test would generate our example view given above (in its blank node form), and pass that to the SWP engine to render. (I am glossing over the _base parameter that is especially critical for 2 to specify the graph that holds the resource to be rendered.) == The SWP class hierarchy == Another thing worth talking about is the role of the subclass hierarchy when working with classes that have ui:prototypes. Since SWP is a programming language, and has subclasses, one might think of it as an object-oriented language. There are indeed some object-oriented concepts in SWP, but I personally found that thinking of SWP in object-oriented terms does more harm than good. SWP is not a traditional object-oriented (or, for that matter, prototype-oriented) language. It is its own thing and fairly unique. So, here are the most important uses of subclassing in SWP: 1. As a simple grouping mechanism in TBCME. If I work on a bunch of classes related to a certain feature, I might make them all subclasses of a common abstract class such as ex:FeatureXyzElements. This makes them appear together in the TBCME class tree, which is convenient for navigation in TBCME, even though it has no effect on the program itself. 2. To avoid having to repeat argument declarations, error prototypes, and head includes on multiple classes. A few select properties, including spin:constraints, ui:errorPrototype and ui:headIncludes, are inherited by subclasses for the purposes of the SWP engine. So, if I have many classes that require a ?projectGraph argument, I might declare it only once on an abstract class ex:ProjectGraphElements, and then make all other classes subclasses of that one. Or, if I have many classes that require the same ui:errorPrototype (e.g., a permission check or configuration check), then I might put that ui:errorPrototype on an abstract class ex:AdminElements and make the other ones subclasses of that one. Just to avoid having to say the same thing in multiple places. There are other uses and patterns related to subclasses in SWP, but I find them less important. == The “other” class hierarchy: meta-classes == It is also important to point out that SWP has two parallel class hierarchies. The “real” class hierarchy is rooted at ui:Element, and includes built-in abstract classes such as ui:ViewElements, ui:Services and ui:Operations. All your classes that have ui:prototypes live as subclasses in this hierarchy. Typically, I create new SWP classes by right-clicking on the appropriate class in that hierarchy and selecting “Create subclass”. The “other” class hierarchy is rooted at ui:NodeClass and contains meta-classes. Your classes will be instances of those meta-classes. This usually happens automatically, and the whole “other” hierarchy can be ignored. But it is useful to know about in case one accidentally wanders into it. The meta-classes mostly exist to make matters confusing. Apart from this, they also have the secondary purpose of making TBCME behave nicely when editing the “real” classes. For example, the ui:prototype field appears on the TBCME form of your classes by virtue of some meta-class magic. It would be nice if TBCME did a better job at hiding that magic! Often, the meta-classes and the “real” classes are distinguished by singular vs. plural names, but this is inconsistent and cannot be relied upon. -- You received this message because you are subscribed to the Google Groups "TopBraid Suite Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to topbraid-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.