Re: do you want to blow your mind?
Re: do you want to blow your mind?
- Subject: Re: do you want to blow your mind?
- From: Mike Schrag <email@hidden>
- Date: Sat, 18 Oct 2008 10:52:59 -0400
particularly given that there will only be one instance of a
WOSwitchComponent on a given parsed page (meaning that if there's a
WOSwitchComponent for an element in your Main component, there will
only be ONE INSTANCE of WOSwitchComponent servicing that slot on
the page for all of your users).
I'm not convinced of that .. yet. i.e., It's not a stateless
component, but then again it's not a subclass of WOComponent but
WODynamicElement. So okay ... back to me first answer :-)
Yeah, exactly ... It's sort of nuts, right?
So the magic is WOComponentReference + WOComponentDefinition +
WOComponent. What happens is that when your template is parsed, it
gets parsed into a bunch of WOComponentReferences. If you understand
WOAssociation, WOComponentReference is like the equivalent concept for
components. That is, you have a handle that says "I represent an
AjaxInPlace with a set of bindings" but it's not a stateful instance,
it just describes how you're going to use it.
During parsing an entire tree of these is built up. It represents
your parsed parse without state. The sort of interesting part is that
these things actually extend WODynamicElement, so they LOOK like
components from the outside. If you recall, every time you do that
you get a new instance of the top level component. You may have
wondered "why". The reason becomes clear with this architecture.
What happens is, and this is the kind of neat and clever part, is that
at runtime, you say pageWithName("MyPage"). You get a new instance
of the top level component. For each parsed element on the page (a
WOComponentReference), the framework will walk down the tree and say
"give me a stateless peer for this WOComponentReference for a
component of this name, and use this set of bindings". It's here,
btw, that it can decide whether subcomponents get new instances or
come from the shared pool. Then the part that I DIDN'T know about --
the way these are connected is that the new instance of a child
component is pushed into a dictionary in the WOComponent parent keyed
off of element ID, so the framework can walk down the parsed tree and
say to the parent, "give me your child component with the elementID
x". If this component has already been materialized, the component
will hand back a subcomponent from its dictionary. If one isn't
there, it will make a new one and push it into the dictionary. So
this starts to make sense, now, why you always get a new top level
component instance -- it's the root of the state tree. There has to
be a root node to hang all these stateful components off of. The
magic method for all of this is actually
WOComponentDefinition._componentInstanceInContext(context), btw.
So fundamentally, there's this stateless tree of elements that
represents my entire parsed page and there's this stateless tree of
WOComponent instances that represent the actual components of the
page. So in normal components, the structure of your page is
basically predetermined -- you have a bunch of WOConditionals,
WOStrings, AjaxInPlace's, etc, all in a tree and page state determines
which page through this graph you take. WOSwitchComponent, though, is
a crazy twist on this. WOSwitchComponent DYNAMICALLY determines its
page structure -- that is, the "parsed side" is indeterminate for a
WOSwitchComponent. And if you look at WOSwitchComponent, this is
exactly what it's doing. When you ask for a "SomeComponent" for has a
cache of the name you ask for mapped to NOT WOComponent, but INSTEAD
WOComponentReferences -- those stateless handles. It's clever as
hell. When it needs the component to work on, it looks up the correct
instance of WOComponent based on the reference that it has cached
(that is shared by everyone!) by asking the context().component() for
a child with the current elementID, and will make one if it doesn't
exist. So WOSwitchComponent takes advantage of this peer concept and
basically builds this structure up itself on-the-fly. When this
clicked for me, it was a "woah .. that's really slick" moment.
All of this finagling on my part was because I wanted to implement a
new type of component that would allow you to, for instance, create a
component on your page that would act like an "embedded page," where
instead of having the result of invokeAction replace the entire page,
it would instead just replace the embedded page component. To do
this, you have to muck with page structure on-the-fly, which is pretty
similar to what WOSwitchComponent does, but changing over time. So I
just pulled up WOSwitchComponent and thought "I'll just base my code
on this - -should be pretty easy" except that I looked at
WOSwitchComponent and decided that it's impossible that it actually
worked right :) But it does, and I began my quest to find out how :)
Incidentally, I THINK (haven't verified yet) that the third parameter
to the constructor of a WODynamicElement, which I've always sort of
wondered its exact purpose, is your stateless-parsed-element-peer. So
you're being handed the reference to your stateless equivalent in the
parse tree. This is my theory, at least. This gives you access to
the structure of your children components, which during the R-R loop
can also be used to access the stateful peers, etc.
So anyway ... That's the long story that probably nobody else cares
about, but I think it's sort of a fascinating aspect of WO, because
it's this crazy and clever underpinning that makes the entire
framework function that I really had no idea about the inner workings
of.
ms
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden