Hi,

At 20:42 3.7.2000 -0400, you wrote:
>       The "io" package includes the XML reader interface, and will
>eventually include more "visitors" that read in or write out the metadata
>(or translate to GUI objects, etc).  It would be great to base this on a
>more generic "Visitor" interface, but I couldn't think of how without
>introducing lots of casting (help me!).

Casting at which point? Do you mean when the metadata structures accept the
visitor and we need to determine the correct callback method? The casting
done there can be abstracted away if you really feel it is necessary. It
will introduce another layer of indirection, and well yeah it would make it
kind of elegant now that I think about it, still not sure if it's all worth
the trouble though  (I don't feel as strongly about casting than I do about
public fields :) Anyhow, the OO way of doing callbacks is to use Commands.

I'm kinda sleepy but let's see if I can get this right (still playing with
the codebase you sent earlier, I hope you committed the same one to the
CVS. Also, this is pseudo as usual :)

You have AbstractMetaData objects that implement the MetaData interface. In
addition, they can have a VisitorAcceptor interface (that's really a horrid
name, I know) that handles the generic visitor access. The interface would
look like this:

interface VisitorAcceptor {
        void accept(Visitor visitor);
}


The visitor interface here is a generic interface for all visitors. It
allows the acceptors to receive a reference to the visitors callback method
via the command interface:

interface Visitor {
        Command getCallbackMethod();
}

Again, the Command interface looks just like it always does:

interface Command {
        void execute();

        // this is specific to ejx metadata
        // might want to have a generic command interface and
        // extend it by creating a EJXCommand interface.
        public void setCommandTarget(AbstractMetaData metadata);

}


Now the concrete implementation of visitors implement the Visitor interface
by producing a concrete Command implementation. The command object knows
the visitor's callback method, even though it's not ever revealed to the
metadata structures:

public class ConcreteVisitor implements Visitor {

        public Command getCallbackMethod() {
                return new ImportCommand(this);
        }


        public void import(AbstractMetaData metadata) {
                
                // do all the infamous business logic here
                // IOW, a bunch of setProperties() once
                // you've parsed the XML
        }
}

public class ImportCommand implements Command {

        public ImportCommand(ConcreteVisitor visitor) {
                this.visitor = visitor;
        }

        public void execute() {
                visitor.import(metadata);
        }

        public void setCommandTarget(AbstractMetaData metadata) {
                this.metadata = metadata;
        }

        private AbstractMetaData metadata;
        private ConcreteVisitor visitor;
}


Finally, the AbstractMetaData object can implement a generic visitor accept
that works for all visitors  as follows:

        ...

        void accept(Visitor visitor) {
                Command cmd = visitor.getCallbackCommand();
                cmd.setCallbackTarget(this);
                cmd.execute();
        }


Did I miss something? Anyhow, like I said, take it with a grain of salt, I
just made it up and am a bit tired :)  I'll try to code this on top of your
metadata structure if it seems worth it (still unclear why no casts,
performance?)


-- Juha



Reply via email to