Hi Rob,
> On 12 Jul 2018, at 01:22, [email protected] 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 [email protected].
For more options, visit https://groups.google.com/d/optout.