[jdom-interest] detach() [eg]

Kenworthy, Edward edward.kenworthy at exchange.co.uk
Mon Apr 30 00:22:30 PDT 2001


Hi Brett

I don't see how this is any easier.

a) It doesn't handle all cases where a document is in an invalid state. ISE
does.
b) What do you do if myElement is *not* a child of parent ? Throw an ISE ?
throw an IAE ? ;-)

Edward

-----Original Message-----
From: Brett McLaughlin [mailto:brett at newInstance.com]
Sent: 29 April 2001 04:06
Cc: jdom-interest at jdom.org
Subject: Re: [jdom-interest] detach() [eg]


I still want to vocally say that I think detach() is not in line with the
rest of the API; at least not on the element being detached. I still don't
see why removeContent() is not fine. I'll grant that perhaps it's not a
one-line answer to this problem, but I'm also not so sure that everything
should be a one-line answer, when it's really sort of silly that way. What's
wrong with

elt.addContent(parent.detach(myElement));

in this case? It allows us to handle the Document case very easily, and
still is easy to understand.

-Brett
----
Brett McLaughlin

Enhydra Strategist
  * http://www.enhydra.org
  * http://www.lutris.com
O'Reilly Author - Java and XML
  * http://www.oreilly.com/catalog/javaxml
  * http://www1.fatbrain.com/asp/bookinfo/bookinfo.asp?theisbn=0596000162

----- Original Message -----
From: "Jason Hunter" <jhunter at collab.net>
To: "Joseph Bowbeer" <jozart at csi.com>
Cc: <jdom-interest at jdom.org>
Sent: Saturday, April 28, 2001 5:33 PM
Subject: Re: [jdom-interest] detach() [eg]


> > My concern is about the impact on consumers of documents.  (XMLOutputter
is
> > a trivial example.)
> >
> >     class Consumer {
> >         void consume(Document doc) {
> >         }
> >     }
>
> I would argue if a document without a root is passed to this method,
> it's a programmer error, appropriate for an ISE.
>
> > (But we've been down this path before.  By trying to be nice, we're
lowering
> > the quality of our API and making it harder for JDOM users to write
robust
> > code.)
>
> Yep, there's no easy answer.  Having RuntimeException be unchecked in
> Java was a similar compromise -- that decision made it harder to write
> robust code but easier to write code in the first place.  :-)
>
> Here's the bottom line so we can end this thread...
>
> Doing a "move" without detach() requires three checks and a lot of
> special casing:
>
> 1) attached to a doc -- call setRootElement() on another placeholder elt
> 2) attached to an elt -- call getParent().removeContent()
> 3) attached to nothing -- know to call nothing or risk NPE
>
> Here's code:
>
> if (elt.isRootElement()) {
>   elt.getDocument().setRootElement(new Element("Bogus"));
> } else if (elt.getParent() != null) {
>   elt.getParent().removeContent(elt);
> }
> newelt.addContent(elt);
>
> It's ugly.  Of course many programmers will just write
>
> newelt.addContent(elt.getParent().removeContent(elt));
>
> ...because it's easier and we even had an experienced JDOM user here
> suggest it.  The problem is although it works most of the time,
> sometimes you get a nasty NPE.
>
> So I'm convinced we need detach().
>
> Having detach() throw an exception if the elt being detached is a root
> is better than not having detach(), and is a good behavior from an
> academic point of view.  But it still leaves some ugly special casing to
> the programmer:
>
> 1) attached to a doc -- call setRootElement() on another
> 2) attached to an elt -- call detach()
> 3) attached to nothing -- call detach()
>
> The code for a move:
>
> if (elt.isRootElement()) {
>   elt.getDocument().setRootElement(new Element("Bogus"));
> } else {
>   elt.detach();
> }
> newelt.addContent(elt);
>
> Not much better, and again many programmers will just write:
>
> newelt.addContent(elt.detach());
>
> ... because it's easier.  But sometime later elt will be a root and
> they'll be surprised with an exception.
>
> Now, let me state I believe the vast majority of use cases where you'd
> detach a root are that you're harvesting the root and don't care about
> the old doc.  A programmer doing the detach understands that if they
> take the root it's gone from the original document, and that's OK
> because they aren't going to use the old doc.  These programmers just
> want to remove the root and use it.
>
> With this in mind, it seems reasonable to somehow make the detach() of a
> root elt succeed.  This behavior gives the programmer no surprise on a
> detach() call because there's no exception to be thrown, and it gives
> the programmer very little surprise that the old document doesn't have a
> root because they were the ones to remove it.
>
> The problem with the original doc not having a root is that XML wants
> all docs to have a root element, and we're trying to provide a
> well-formedness guarantee as a feature.  So we have three choices:
>
> 1) Add a placeholder.  This is what we do now.  It means we can say "all
> docs are well formed", and it allows a programmer to detach a root
> without jumping through hoops.  But this thread started because people
> didn't like it.
>
> 2) Return null from getRootElement() and a list without an Element from
> getMixedContent().  This suffers from the problem that someone might
> output the document and not realize it's not well formed.  It totally
> punts on well-formedness and makes the user check.
>
> 3) Report an ISE on getRootElement() and getMixedContent() on a doc
> whose root has been detached or which has been constructed without a
> root.  This allows the "move" FAQ answer to be
> newelt.addContent(elt.detach()) with that call working in all cases.  It
> removes most surprise from the programmer because only if they try to
> access a root element which *they earlier removed* will they hit an
> exception.  Even the vast majority of people who don't realize XML
> requires each doc to have a root will understand the original rootless
> document is pretty useless without data and they won't call on it.  We'd
> still enforce well-formedness, but with regard to the root element it's
> a "lazy" enforcement.
>
>
> No solution above is perfect, but we have to decide and move on.  The
> top two favorites in my mind and that I've heard supported here are (a)
> throwing an exception on root.detach() or (b) allowing the detach() but
> throwing an ISE upon later rootless document use.  Considering the code
> shown above for option (a) in that you would have to create and
> substitute your own bogus element before moving a root, I prefer (b).
>
> So, unless there are any *new* facts on the topic, I'd like to go with
> (b).
>
> -jh-
> _______________________________________________
> To control your jdom-interest membership:
>
http://lists.denveronline.net/mailman/options/jdom-interest/youraddr@yourhos
t.com

_______________________________________________
To control your jdom-interest membership:
http://lists.denveronline.net/mailman/options/jdom-interest/youraddr@yourhos
t.com



More information about the jdom-interest mailing list