Hi Ed,
Many thanks for your comments and suggestions. I have attached a partial
project containing a schema that illustrates the kind of keyref patterns
that I have encountered - they are a fairly simple subset.
I was originally thinking in terms of a metamodel-driven implementation
(generative or reflective) but given your suggestions I did try
overriding the Resource.getURIFragment(EObject) and
InternalEObject.eResolveProxy(InternalEObject) methods to store/resolve
the specific keys. The attached code just about works but it turned
into the most hideous kludge ;-(
It's hard to state categorically what a usable subset of key/keyref
functionality might be in the general sense but it does seem to me that
EReference.eKeys() might do the trick if there was an option to tell it
to use a single bare key value for same-doc references rather than a
hierarchical URI fragment path. BTW given the experience of writing the
attached code I rather suspect that the issue would be resolving key
values rather than computing them.
Renewed thanks, and best regards,
Adrian.
"Ed Merks" <merks@xxxxxxxxxx <mailto:merks@xxxxxxxxxx>> wrote in
message news:fnlbhl$h5n$1@xxxxxxxxxxxxxxxxxxxx
Adrian,
Comments below.
Adrian Price wrote:
Good day,
First, my apologies for the length of this posting; I've tried to be
concise.
People often accuse me of being to verbose, but I figure it's good
to cover all the important details.
My last two EMF consulting engagements have involved the use of EMF in
conjunction with published application schemas bearing XSD unique/key-keyref
constraints on non-containment references, which EMF does not currently
support. Use of xsd:ID would have imposed an unacceptably restrictive
document-wide key uniqueness constraint. The net result is a rather
less-than-usable generated model API with such references represented as
string-type EAttributes rather than typesafe EReferences. Consequently,
clients require hand-cranked key<-->object accessor/lookup code and JFace
viewers, data binding support, etc. cannot readily be used.
The problem is that the full generality of this constructs in schema
don't map well into simple concepts...
Now, you can add ecore:reference attributes to the schema xsd:attribute,
which causes XSD2Ecore to import the attribute as an EReference, but that
does not solve the problem because EMF still uses the positional URI
fragment segment syntax. Adding ecore:keys attributes doesn't help either,
because EMF's //@<feature>[<key>='<value>'] syntax differs from the plain
key value syntax implied by XSD keyref@field.
Yes, the value for a keyref is really more like an ID with a more
localized scope.
I could not find an easy way
to override fragment generation or lookup (because neither Resource
getURIFragment(EObject) nor getEObject(String) pass the EReference context).
Yep. That's why we can't produce "relative fragment paths either".
Also, JET2 has a fully functional XPath implementation that can navigate EMF
models. It seems to need ExtendedMetaData annotations in the domain
meta-model to map the XPath element and attribute references to Ecore
EReferences or EAttributes (XSD2Ecore imports these annotations
automatically). I saw this as a potential basis for evaluating key scopes to
support key lookup and validation.
There are callbacks on the owner of the proxy, so that potentially a
hook at which to resolve such proxies relative to the owner.
public EObject eResolveProxy(InternalEObject proxy)
{
return EcoreUtil.resolve(proxy, this);
}
And you could specialize Resource.getURIFragment with the assumption
that the reference objects will only be referenced in a way that can
use some local attributes as the key.
Ed Merks stated in dnu9m6$c4e$1@xxxxxxxxxxxxxxxx (Dec' 05):
Yes, there is no support for key/keyref and no short term plans to add
it. There really aren't even long term plans to add it. The whole
design is just so XML-centric and maps so very poorly at the metadata
level. There's very little you can do with the fully general XPath
expressions until you have instance data to match it against. I.e.,
there is no requirement that the referenced ElementB has an @AttrA in
the schema, only that the instances have such an attribute, but each
instance could be a different complex type instance with a different
version of @AttrA of a different type even. It's kind of a mess, in my
opinion...
Ed's comments seem to suggest that it would not be possible for EMF codegen
to generate key-keyref constraints into 'minimally reflective' methods. Even
so, I'm wondering whether a reflective/interpretive approach might be
feasible given the existence of JET2's EMF XPath support. My guess is that
the performance hit on load/save would be an acceptable tradeoff against the
enhanced client API.
Finally, my research turned up the following reference:
http://www.priorartdatabase.com/IPCOM/000157944/ ("Modeling XSD:key and
XSD:keyref Using EMF"). From the (incomplete) text it looks as if someone at
IBM has looked at the issue and actually come up with at least a design, if
not an implementation. Does anyone have any information on this?
No one ever discussed writing a disclosure with me. Of course I
help folks all the time and I'm never sure what they go off and do
with the information I share freely.
I'd be interested if anyone has thoughts on this topic.
Given that there is a decent hook for which "relative fragment"
paths could be evaluated (both in BasicEObject and perhaps in in the
EcoreUtil method I suspect the trickiest issue is how get XML
serialization to generate such a thing. It would be interesting to
see some real world examples (or facsimiles there of) of scenarios
you've encountered. As I said before, the full generality is kind
of a little much, but I'll bet the real world use cases are far
simpler and might be supportable with a few simple annotations. So
if you would care to share some examples/scenarios, I could give
some thought to how such patterns might be supported. Perhaps open
a bugzilla feature request and attach examples there and we can
discuss some possible approaches.
Thanks,
Adrian Price
TIBCO Software, Inc.