For example, the StreamManager of NetFish checks the MIME content type of the stream to determine the next action. If the incoming stream is a html document, the MIME content type is text/html. The StreamMangaer then selects HtmlParser to parse the stream. If the stream contains the data stream of a gif file, the MIME content type is image/gif. In this case, two actions are possible. Either an ImageViewer is used to display the image, or a DummyFilter saves the stream into a temporary file. It depends on whether HyperApp has instructed StreamManager to spawn a new window or not. If HyperApp has sent a spawn: true message to StreamManager, then ImageViewer is chosen. Otherwise, DummyFilter is used.
StreamManager has a class instance variable TypeMap which stores the filters and viewers used for each type of HyperComponents. TypeMap is an instance of ActionMap. ActionMap has a dictionary which maps a symbol to an ActionEntry ActionEntry has a filter class symbol, a Viewer class symbol and a subtypeActionMap. The subtypeActionMap is used when multiple types are needed to determine the Viewer and Filter used. For example, if SMWeb, a concrete subclass of StreamManager used in NetFish, is asked to return the filter for MIME type #text and subtype #html. It returns a HtmlParser. However, if type #text and #mchung is asked for, then a CodeFilter is returned.
The mechanism to search for the Filters and Viewers is a recursive action. It is implemented in ActionMap. Basically, it first searches the type first, and then get an ActionEntry. Then, ActionMap checks if there is a subtypeActionMap. If there is, the subtypeActionMap is asked to return the Viewer or Filter. If found, the one returned by subtypeActionMap is used. Otherwise, the first one found by ActionMap is returned.
The programmer who uses the class ActionMap only need to fill out a collection in the following format and then send the message actionMapFor: to the class ActionMap to get an instance of ActionMap that is initialized by that collection. Below is an example.
fillMap "Fill the content of TypeMap." |c| c :=#( #( #text #PlainTextFilter nil #( #(#html #HtmlParser nil #()) #(#mchung #CodeFilter nil #()) ) ) #( #image #BinaryFilter #ImageViewer #()) ). ^self actionMapFor: c
c is a collection of the definition of ActionEntry. Each definition has 5 parts #( type, filter class symbol, viewer class symbol, subtypeActionMap). SubtypeActionMap is an ActionMap for the subtypes. In the above example, it defines the ActionMap for the type #text and #image. In the ActionEntry of #text, it contains another ActionMap for the subtypes. In that subtype ActionMap, it has ActionEntry for the type #html and #mchung.