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: Guido Neitzer <email@hidden>
- Date: Sun, 19 Oct 2008 11:30:41 -0600
Hey Mike,
thanks for sharing that insight! I have no real need for that at the
moment, but I will go back to your coming blog post and learn more
about the inner parts of WO. Very good explanation by the way ...
(something in my brain somehow autocorrected the sentences you
mentioned ... ;-))
cug
On 18.10.2008, at 08:52, Mike Schrag wrote:
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
_______________________________________________
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