OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

 


 

   Re: [xml-dev] Observer Pattern and Errors (Was: SAX IoC Errors)

[ Lists Home | Date Index | Thread Index ]

* Peter Hunsberger <peter.hunsberger@gmail.com> [2005-01-12 11:05]:
> On Sun, 9 Jan 2005 03:09:45 -0500, Alan Gutierrez
> <alan-xml-dev@engrm.com> wrote:

> I'm back, still no time...

> >    I'm not using instanceof anywhere in the SAX Strategy library.
> >    If it were introduced, it would indicate an error in design to me.
> >    I'm that way about instanceof. :^{

> I understand where you are coming from, but I'm not quite that
> dogmatic.  In particular, I consider it more of a Java design flaw
> that you can't down cast automatically.  In particular, since you're
> doing a framework it makes sense that the users of the framework will
> want to exploit polymorphism on some basic underlying interfaces (or
> that you want to hide the underlying details via polymorphism).  The
> users of the framework should thus never see an "instanceof" in their
> code, but the framework itself might not be so lucky; the framework
> looks for special case interface extensions as a way of understanding
> context but when everything is upcast to the simplest version of the
> interface you're stuck with instanceof or try/catch on casts or
> introspection - all ugly.  The alternative is to use setter/getter
> configuration but that can result in one giant Class doing everything
> which is also an anti-pattern...

    Later in this message (I'm working backwards) I come to the
    conclusion that IoC isn't at play. It's a more general problem
    of error handling within an observer pattern.
    
    Does it make sense to unwind the stack when you are using
    callbacks? Probably good to find a pattern that puts error
    handling closer to the callback.

    I agree that in a container, instanceof is necessary to get the
    ball rolling. Reflection is good for pluggables. I'm not doing
    that here, so that's why it would strike me as an error in design.

> >    A Strategy for error handling wouldn't make much sense unless it
> >    existed as a Strategy for a SAX handler that is up stream.

> >    There three concepts in the model

> >        2) The stacks of events do exist. There is an Event object
> >            that acts as a stack node. There is a separate Lexeme
> >            interface heirarchy that models the data (events,
> >            characters, processingInstructions, etc.).
> > 
> >            The Lexemes are separated since they can be recorded as
> >            a stream and replayed. The stack for each lexeme would
> >            be derived when the lexemes are replayed.
> > 
> >            The stack helps to generate locator information. It
> >            helps in creating filter logic, dispatching.

> >            I have some simple matching classes that I use currently.
> > 
> >            The Event objects also have cubbyholes where a program
> >            can put state. This is rarely used in leiu of...

> Ok, maybe the Event object is what you need to extend.  Extend the
> cubbyholes or test them or whatever to determine error "states"?

    Hmm... No. The Event models the SAX event. It actually doesn't
    get used much, not directly. It is used to create a stack of
    element events, but the cubbyholes are not useful to an
    application, unless the application is XML specific, like
    serializing, for example. One might keep  track of whether their
    where child elements and print <foo></foo> or <foo/> as a result. 

    There are still more cubbyholes in the Campaign stack. These are
    specialized since the Campaign stack is not navigable,
    
    There is not stack iterator, their are the post methods to send
    messages up stack and the seek methods to look at cubbyholes set
    by Campaigns up stack.

    So, this stack, is not the application stack. It's the stack I
    discuss below. 

> > 
> >            At any point you can launch a new Strategy. The context
> >            for a Strategy is a Campaign.
> > 
> >            As of today, the Campaign stack is also a message
> >            conduit.
> > 
> >            So, there are now two separate models for messages. SAX
> >            Events, as in Strategy class above. And this here:
> > 
> >            public interface Receptionist {
> >                void message(Campaign campaign, Event event, Message message) {
> >                }
> >            }
> > 
> >            public interface Message {
> >                CampaignKey key();
> >                Object data();
> >                void intercept();
> >            }
> > 
> >            public interface Campaign {
> >                /* Send messages up stack. */
> >                void hook(CampaignKey key, Receptionist receptionist);
> >                void unhook(CampaignKey key);
> >                void post(CampaignKey key, Object data);
> > 
> >                /* Preserve state for down stack. */
> >                Object put(CampaignKey key, Object data);
> >                Object get(CampaignKey key);
> >                Object seek(CampaignKey key);
> >            }
> > 
> >            The campaign stack is different from the event stack,
> >            yet it is still tied to the stream of events. Once a
> >            Strategy is launched, it's Campaign is not popped off
> >            the Campaign stack until the endElement event during
> >            which it occured (did I say that right?).

> Ok, now you've got "Message:, what happened to "Event" ?  Perhaps
> these overlapping concepts?

    They are separate concepts, shared pattern (observer).

    public interface Event {
        /* Lexeme.  */
        Lexeme getLexeme();

        /* Lexeme cast to different types. */
        Element getElement();
        Characters getCharacters();
        ProcessingInstruction getProcessingInstruction();

        /* Stack o' events.  */
        EventStack getEventStack();
        EventStack.Cursor getEventCursor();

        /* Cubbyholes.  */
        public Object put(Object key, Object value);
        public Object get(Object key);

        public boolean contains(Object key);
    }

    A lexeme:

    public interface Lexeme {
        public Lexeme toImmutable();
        public boolean isImmutable();

        public short getType();

        public void forward(EventSink sink);
    }

    public interface Characters extends Lexeme {
        public CharacterRange getCharacterRange();
        public boolean isCDATA();
        public boolean isIgnorableWhitespace();
    }

    For use with:

    public interface Strategy {
        void launched(Campaign campaign, Event event);

        void startElement(Campaign campaign, Event event);
        void characters(Campaign campaign, Event event);
        void comment(Campaign campaign, Event event);
        void processingInstruction(Campaign campaign, Event event);
        void endElement(Campaign campaign, Event event, Campaign concluding);

        void concluding(Campaign campaign, Event event);
    }

    See? Two stacks. SAX event stack. Application strategy stack.

> >    Errors are a flavor of Message, and not Strategy, then...

> Sounds like it.

> > 
> >    In any case, this last post isn't so much about Errors, as it is
> >    about using SAX to drive Java in ala IoC.

> The whole idea of how to use IOC for how to handle Errors in a
> framework seems a little murky; from this discussion it almost seems
> like you need some meta-IOC pattern: IOC is driven through
> configuration, configuration itself can result in errors, thus Error
> handling is forced to become a primitive concept, but in your case you
> also want it to be a high level concept.  You need a try/catch
> framework around your framework.  As such, having testable components
> that case the exterior framework to be invoked in the same way as
> otherwise unhandable primitive exceptions seems the way to go:

    Is IoC really what I'm doing here?

    Although "don't call us, we'll call you" is in play here, I
    don't think I'm developing something as abstract as
    PicoContainer. It's more like Swing. Construction errors are
    caught at compile time. You can't addActionListener(new File());

> BlowUpNowException for low level errors that indicate the whole
> framework is out of wack.

    Again, compile.

    I'm not using IoC then, because there not configuration,
    reflection complexity (yet). The errors that I'm looking to
    process are occuring during processing.

    The framework might still be totally out of wack, for some
    Strategy composition. There are programming errors, composition
    errors, that could only be detected once a particular branch was
    followed. That should be unrecoverable, since it is programming
    error and ought to fail fast.

    In the end the options will be ignore, raise, or retry. Until
    someone makes that decision, the error message keeps getting
    shuffled about.

> ErrorMessage (ErrorEvent?) throws BlowUpNow (and variations) for some
> configurable instance of a test for transport of Errors that may or
> may not be handled by some specific tester.  (Allows orthogonal error
> mangement: degrees of error handled across degrees of error
> tolerance).

    I'm not sure I understand this last bit. What does it mean? "for
    some configurable instance of a test for transport"?

-- 
Alan Gutierrez - alan@engrm.com




 

News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 2001 XML.org. This site is hosted by OASIS