Mail Archive Home | zeus List | January 2001 Index
| <-- Date Index --> | <-- Thread Index --> |
OK-
So here's where things are. Currently, we have a fairly lame data binding
implementation. I'm completely dissatisfied with it, and so expect that
almost all of it will be rewritten, especially the SchemaGenerator. That's
actually OK, as it only took me about a week to write, anyway.
In this mail, I'm going to lay out the architecture associated with where
we're going. In a later mail, also today (I hope), I'm going to lay out the
plan of attack and set some milestone dates. Fair warning: I'm going to move
very fast on this first round, as I want to get this into use in some parts
of Enhydra that would need it within about 3 weeks. So I'm going to push. I
welcome help, but understand if you "sign up" I'm going to need you to move
quickly, at least until we get to this first release. Then we'll take a deep
breath and proceed at a more rational pace ;-) Additionally, the website
probably won't be updated until that push is over, as well, and all
communication will be here, on the list. Then I'll retrofit in requirements
and Javadoc and the like.
So here we go:
First, I want to introduce the concept of "bindings." While this is an
overused term, what I want to hone in on is that the process of XML data
binding is about taking a set of constraints (so far, we have assumed these
are in the form of an XML Schema. I'm going to step back from that in a
moment) and mapping those to Java constructs. In essence, the mapping is
binding a constraint to a Java object. However, in looking at it this way, I
see a fundamental limitation with most data binding implementations. They
hard code in the binding from a set of constraints (a schema) directly to a
Java object. Thus, adding support for DTDs, or perhaps Relax, or even
updating a schema rec (as we have all struggled with here) involves changing
the actual Java class generation code. I think this is very bad. Instead,
all that should be changed is the MAPPING. So let's look at my silly ASCII
art of what currently goes on in data binding frameworks (including the
Enhydra one on the FTP site):
XML Schema ----> [SchemaMapper] ----> Java classes (written to output
stream)
What I want to see is this:
XML Schema ----> [SchemaBinder] ----> (Bindings) ---->
[Generator] ----> Java classes (written to some output)
What's cool is this allows, very easily, this:
XML Schema ----> [SchemaBinder]--\
\
DTD -----------> [DTDBinder] --------> (Bindings) ---> [Generator] --->
Java classes
/
Relax schema --> [RelaxBinder]---/
So now adding a new constraint type, or even changing a schema spec, means
only changing the XXXBinder, which is isolated from code generation. Make
sense? I'm quite happy with it myself, and can't find any flaws. The only
possible downside that I see (other than a little more work) is some speed
loss in the abstraction. However, I see class generation done almost
exclusively as a pre-step, not a runtime step, so that's OK. And we can
optimize later as needed.
So with that as a presupposition, I think we have some new constructs to
work out:
Binder (interface)
Binding (interface)
Generator (interface)
The first, Binder, will define how a set of constraints can be supplied, and
provide a means to extract a set of Bindings from it that represent those
constraints. Once the Bindings have been extracted, they are
indistinguishable from any other set of Bindings, regardless of the input
type (so a DTD and schema that are equivalent would produce identical
Bindings). [As a corollary, and later project, this makes conversion from a
DTD to a schema sort of trivial, and would be cool to write, as I have seen
little stable work in this area].
As for Bindings, I see two core classes:
Objects, and Properties. However, I don't want to call anything an object.
And there is clearly confusion over why a property would not be an object.
So instead, I prefer:
Containers and Properties. These would both derive from Binding, and the
former is of course capable of "containing" things, while the latter is a
member of something. In addition, you have further breakdown: an
AtomicProperty would be a simple name/value/type deal. However, a
ContainerProperty would be a property of another Container, yet also could
contain things itself (this is essentially an Object, like a List). So I see
this hierarchy in our Bindings:
Binding
/ \
/ \
Container Property
\ / \
\ / \
ContainerProperty AtomicProperty
I can't quite come up with a Container derivation that isn't a Property,
though. Of course, the base Container could be a top level object. So you
might have:
Container
|
|- AtomicProperty
|
|- AtomicProperty
|
|- ContainerProperty
|
|- AtomicProperty
|
|- ContainerProperty
(And so on)
Make sense? That, as simple as it is, really represents the types you end up
with in Java. I don't see a need to (at least at this stage) define
accessor/mutator method bindings, as for any property, it's simple to derive
from that the appropriate getXXX() and setXXX() methods to work upon it. And
if something isn't a property, it should have accessors and mutators anyway.
That really leaves only the Generator. This has one core method:
public void generate(Binding binding, Result result);
This will take in a binding, and then output the resultant classes to a
Result. The reason that it doesn't take a Binder is that it is possible that
we may want to provide transformations of Bindings. This is the JSR-31
full-blown version where there is a "binding schema" that specifies mappings
from the constraints to class generation. For example, a Foo in the
constraints may actually become a Bar in Java. We aren't going to add this
into the first version, but this framework easily allows for it, as I see
it. So we'll provide an initial SimpleGenerator, that probably provides (as
convenience):
public void generate(Binder binder, Result result) {
generate(binder.getBinding(), result);
}
More complex Generator impls can come later.
[Side Note: Result abstracts an output. We will provide a concrete
StreamResult, and we will also have Source for input, and provide
StreamSource. If these ring a bell, they are from the TRAX concept, which I
think is a good idea]
So with all that off my chest, here's what I see needs to be done:
Package structure:
org.enhydra.zeus [Core]
.Marshaller
.Unmarshaller
.Result
.Source
.binders
.Binder
.SchemaBinder
.DTDBinder
.generators
.Generator
.SimpleGenerator
.bindings
.Binding
.Property
.Container
.ContainerProperty
.AtomicProperty
.stream
.StreamSource
.StreamResult
Yes, this does greatly increase the number of classes from the original 5 or
so ;-) At the same time, it is a far more robust design, and is far below
the huge number in alternatives. So you're all welcome to comment. I'm going
to put together a plan of attack in terms of timeline, and probably start
coding today or tomorrow morning. If you want to jump in, come on. If you
think I'm a moron, you can tell me, but I'm actually pretty settled on this
design, so you better have good arguments and a good alternative ;-)
Finally, coding begins tomorrow in any case, so even if it's not perfect,
we'll settle on something today and move forward.
Hope you're all excited that we're getting into gear here... I am ;-)
-Brett
-----------------------------------------------------------------------------
To unsubscribe from this mailing list, send email to majordomo@xxxxxxxxxxx
with the text "unsubscribe binding" in the body of the email.
If you have other questions regarding this mailing list, send email to
the list admin at owner-binding@xxxxxxxxxxxx
| <-- Date Index --> | <-- Thread Index --> |
Powered by MHonArc.
Copyright © 1999-2005, ObjectWeb Consortium | contact | webmaster.