System for connecting a client to a server with a protocol stack dynamically constructed by using top and bottom service descriptions as query parameters5864668Abstract A method and system for providing services in an object oriented system. The method and system are in the form of an interface reference framework of objects which create services in response to requests. Clients request services which are created in response to the requests. In response to the request the framework first develops a description of the service. The description is in the form of a stack of descriptions of services. From the stack descriptions the actual services are created by maker objects. Claims Having thus described our invention, what we claim as new, and desire to secure by letters patent is: Description FIELD OF THE INVENTION
______________________________________
TPrinterDeviceChannelMaker* theDeviceChannelMakerPtr;
TPrinterDeviceChannel* theDeviceChannelPtr;
TInterfaceReference* theReferencePtr;
theReferencePtr = this->GetInterfaceReference();
theReferencePtr->SetTopInterface(kPrinterDeviceChannel);
theDeviceChannelMakerPtr = (TPrinterDeviceChannelMaker*)
theReferencePtr->Activate();
theDeviceChannelPtr = theDeviceChannelMakerPtr->
GetDeviceChannel();
______________________________________
TNetworkInterfaceReference 908 The purpose of TNetworkInterfaceReference 908 is to shield clients from the details of how a service for a remote device is created. An active TNetworkInterfaceReference object represents access to a remote service. TNetworkInterfaceReference 908 has the following attributes 910: Service Reference: TServiceReference 910--This value specifies the network service reference to use when the TNetworkInterfaceReference object is activated. When a TNetworkInterfaceReference 908 object is activated, it uses the "top" interface and the TServiceReference attribute 910 to create the service stack. The bottom service of this service stack is a TRequestSenderStream object. FIG. 10 illustrates possible variations of the service stacks. If the top interface is "TRequestSenderStream", then the stack consists of just this single service, as shown by 1000. If the "top" interface is "printer", then the set of services, with "printer" on top and "TRequestSenderStream" on bottom, is created. This is demonstrated by FIG. 10, at items 1002 and 1004. If the "top" interface is "modem", then the set of services, with "modem" on top and "TRequestSenderStream" on bottom, is created. This is demonstrated by FIG. 10, at items 1006 and 1008. THardwareInterfaceReference 904 The purpose of THardwareInterfaceReference 904 is to shield clients from the details of how a service for a local device is created. An active THardwareInterfaceReference object 904 represents access to a service provided by a real local device. THardwareInterfaceReference has the following attributes 906: Connector: THardwareInterfaceHandle--THardwareInterfaceHandle represents a connector on the device actually performing the service the interface reference represents. THardwareInterfaceReference 906 can determine the absolute "bottom" interface required to construct the service stack by following this connector's hardware connection. UseConnectorName: Boolean--If TRUE, then when the interface reference object is activated, it will ignore the given "top" interface name and instead, use the InterfaceName in the connector as the "top" interface name. This is useful for clients who know what abstract protocol they must use, but don't want to specify a concrete protocol. For example, a client may use a pointing device protocol, but may not want to get involved with the decision of whether to use "LogiTechPointingDevice" protocol or "AppleADBMouse" protocol. This decision is made automatically by the THardwareInterfaceReference object 904 if the UseConnectorName value is set to TRUE. As shown and discussed above with respect to FIGS. 4 and 5, when a THardwareInterfaceReference object is activated, it uses the "top" interface and the "bottom" interface, determined from the THardwareInterfaceHandle attribute, to create the service stack. TInterfaceMaker Interface Maker Classes (FIG. 11): Developed by access manager writers, service class providers or anybody. Used internally by the Interface Reference classes to create a service. The purpose of TInterfaceMaker 1100 is to insulate all of the service provider classes from the service stack framework and to provide a limited amount of typesafety (e.g. no void*). Each maker object represents the ability to create and initialize a particular service. The interface reference framework deals directly with interface maker objects, NOT services. For example, to create a service, an interface reference calls the Activate method (1104, 1108, 1112) on the maker object (1102, 1106, 1110), which creates and initializes the service. The interface reference object never directly touches the service. Never. The reason for this extra level of indirection is so we don't require every service in the system to derive from a single class defined by the Interface Reference framework. For example, a TSerialACIA6850 access manager class is not required to derive from any class in the Interface Reference framework. Service makers have very little overhead and are simple to develop. Service makers belong to a hierarchy dictated by the interface reference framework. FIGS. 12 and 13 contrast the hierarchy restrictions of service makers to the hierarchy freedoms of services. Notice that makers have TInterfaceMaker 1200 as a parent. Services on the other hand are free to belong to whatever hierarchy their authors desire. An active subclass of a TInterfaceMaker object 1200 may be down-cast into the appropriate sub-type to safely obtain a pointer to the real service object. It provides no protocol. In the example of FIG. 12, a client would down-cast his TInterfaceMaker 1200 pointer to TUARTAccessManagerMaker 1206 and then safely call GetAccessManager 1208, which returns a pointer to a TUARTAccessManager 1300. The following more concisely defines the relationships between TUARTAcessManagerMaker 1206 and TUARTAcessManager 1300:
______________________________________
TUARTAccessManagerMaker* theUARTAccessManager
MakerPtr;
TUARTAccessManager* theUARTAccessManagerPtr;
theUARTAccessManagerMakerPtr =
(TUARTAccess ManagerMaker*)anInterfaceReferencePtr->
Activate();
theUARTAccessManagerPtr = theUARTAccessManagerMakerPtr->
GetAccessManager()
______________________________________
TAccessManagerMaker 1202 A TAccessManagerMaker object 1202 creates and activates an access manager. The access manager arbitrates access to the device identified by the THardwareInterfaceIdentifier object passed in to the Activate method. The access manager is not required to derive from an Interface Reference base class. This subclass of TInterfaceMaker 1200 is used to create the bottom service of a service stack. TAccessManagerMaker objects 1202 are created by TInterfaceReference objects when the TInterfaceReference object is activated. The TInterfaceReference passes in the THardwareInterfaceIdentifier object which represents the "metal" the Access Manager controls. TUpperInterfaceMaker A TUpperInterfaceMaker object allows TInterfaceMaker to create and activate a specific service object on top of some other service. This subclass of TInterfaceReference is used to create and activate a specific service object on top of some other service. This subclass of TInterfaceMaker is used to create non-bottom services of a service stack. The service is not required to derive from an Interface Reference base class. TUpperInterfaceMaker objects are created by TInterfaceReference objects when the TInterfaceReference object is activated. TInterfaceBundle 1400 Interface Bundle Class (FIG. 14): Developed by access manager writers or service class providers Used directly by services to provide configuration information. An instance of a TInterfaceBundle 1400 represents encapsulated information specific to a particular service. A bundle can be passed into service makers polymorphically at activation time. TInterfaceBundle 1400 is subclassed to encapsulate the information specific to a particular type of service. An instance of a TInterfaceBundle 1400 can be streamed to a file. Key Scenarios Activate a THardwareInterfaceReference--Overview #1 This scenario is presented twice; once using Booch notation and once using VDL (Visual Design Language) notation. This was done because neither notation does an excellent job of conveying the process of service stack activation. Scenario: A client has a TInterfaceReference pointer to an object whose actual subclass is THardwareInterfaceReference and whose top interface is set to "Printer". The client calls its Activated method. Activation occurs in two stages: (I) Creation of a stack description and (II) creation of the service stack. FIG. 15 illustrates the hardware configuration for this scenario. Handles 1500 and 1510 are objects used to reference the hardware components. The THardwareInterfaceReference object 1508, the printer's connector 1514 (an attribute of the THardwareInterfaceReference object), the connector's identifier object 1516, the connection object 1512, the connector the printer is connected to 1502, the connector's identifier object 1504 and the "metal" 1506. (I) Creation of the stack description (1) The first step the THardwareReference object must perform in order to create the stack description is to get the "bottom" interface. The bottom interface, in this scenario, is found as follows. First, access the THardwareInterfaceReference object's connector attribute 1514. Next, retrieve the THardwareInterfaceIdentifier object 1516 from it and test it. The identifier can not be activated, so we continue. Next, the THardwareInterfaceReference object retrieves the connection object 1512 from the printer's connector. The other end 1502 is retrieved from the connection. The THardwareInterfaceIdentifier object 1504 is retrieved from it and tested. This identifier object is activatable, so we can stop. It specifies the bottom interface "6850". (2) At this stage, we know the very Top ("Printer") and the very Bottom ("6850") interface of our service stack. The next step involves searching through the file system (and potentially NuBus ROM) looking for the set of services which can be joined to form the required service stack (this can be conveniently implemented by subclassing TLocator or TFSLocator). FIG. 16 illustrates a hypothetical "pool" 1600 of service maker entities (i.e. these are the entities which would be found from a TServiceMakerLocator property search). Each entity in the pool represents one TServiceMaker entity which is "installed" on the system. Each entity is identified by its top and bottom interface. The dashed lines 1602 indicate the path we would find for our THardwareInterfaceReference object. (3) The calculated stack "description" for our THardwareInterfaceReference object is defined by the entities connected by the dotted line in FIG. 16. (II) Creation of the stack (1) The THardwareReference object creates the stack in the following order, as shown in FIG. 17: (a) Create the bottom most TInterfaceMaker object in the stack description. The created object 1700 is an instance of the class 1800 shown in FIG. 18. It is activated by passing in the TInterfaceIdentifier retrieved from the THardwareInterface object representing this ACIA port. FIG. 18 illustrates numerous classes, but only particular classes related to FIG. 17 will be discussed. Many of the relationships shown in FIG. 18 have been discussed previously. (b) The TInterfaceMaker object creates its corresponding service (an access manager) and calls ho, passing in the same TInterfaceIdentifier. This new service is labeled 1702 in and is an instance of class 1802 in FIG. 18. (c) The THardwareReference object continues by getting the next TInterfaceMaker object from the stack description (this is a TUpperInterfaceMaker). It Activates the TUpperInterfaceMaker, passing in the TAccessManagerMaker object 1700. Next comes the tricky part. Knowing full well that the TAccessManagerMaker object passed into it is an ACIA Maker (that's what we promise and it works if the properties don't lie), it down casts it to the proper type of maker and asks it for the service 1702. The result of this operation is access to the ACIA Access Manager. (d) Next, the TUpperInterfaceMaker object creates its corresponding service (which can be derived from anything), and calls go, passing it the ACIA Access Manager. (e) The THardwareReference object continues by getting the next TInterfaceMaker object from the stack description (another TUpperInterfaceMaker). It Activates it, passing in the TAccessManagerMaker object 1704, of class 1804. The down cast magic happens again and asks the TUpperInterfaceMaker object passed in for the service 1706, of class 1806. The result is the Serial-ACIA service. (f) Finally, the TUpperInterfaceMaker object creates its corresponding service 1710, of class 1810 calls for passing it the Serial-ACIA service. Now the service stack is complete. The THardwareReference object returns as the result of activate, the top most TInterfaceMaker 1708, of class 1808. Clients may then do the down cast thing to the result and gain access to the top-most service in the stack. Activate a THardwareInterfaceReference--Overview #2 Scenario: A client has a TInterfaceReference pointer to an object whose actual subclass is THardwareInterfaceReference. The client calls its Activated method which executes in two stages: (I) creation of the stack description and (H) creation of the stack. (I) Creation of the stack description (FIG. 19) The creation of the stack description for a THardwareInterfaceReference object 1908 for a Top Interface 1906 involves the following steps: First, we get the "bottom" interface from the hardware configuration framework 1900. Next, we locate the set of services 1902 which satisfy the required interfaces. Finally, we calculate the stack description 1904. This is accomplished by matching the top interface of one service with the bottom interface of another service, until we find the set of services which can be stacked one on top of the other to form a stack with the proper top and bottom interfaces. There is an assumption that there will only be one service stack description calculated from this process. If more than one stack description is found, then perhaps an exception could be generated. Note: The service stack itself is not actually created in this process, just a description of the stack. The stack description consists of an ordered list of references to interface makers. Each interface maker knows how to make its corresponding service and is called on to do so in the next stage of our scenario. (II) Creation of the stack: The creation of the service stack is shown twice. This first section presents a brief overview. The second section presents a more detailed version. Overview FIG. 20 illustrates the overall operation of stack creation for THardwareInterfaceReference. The creation of the service stack involves iterating across the stack description 2008. For each interface maker "reference" 2010 in the stack description, we do the following. First, create an interface maker object 2000. Next, activate the interface maker object, passing in the appropriate arguments (if it's an Access Manager Maker, pass in a THardwareInterfaceIdentifier 2002; if it's an Upper Interface Maker, pass in a pointer to the TInterfaceMaker object below it). If available, the corresponding TInterfaceBundle object 2004 is given to the interface maker object 2000. Finally, the interface maker object 2000 creates its corresponding service object 2006. The interface maker object 2000 initializes the service object 2006. It is intimately aware of what information is required (e.g. THardwareInterfaceIdentifier, pointer to the TInterfaceMaker object below it, TInterfaceBundle object, etc.). Details This section presents a detailed VDL scenario of how a service stack is created. As shown in FIG. 21, the THardwareInterfaceReference object 2104 creates the stack in the following order: (1) Create the bottom-most TInterfaceMaker object 2112 in the stack description 2102 (the created object is an instance of the class shown in FIG. 20 with a 2000 beside it). The stack description is based on the collection of services represented by 2100. The TInterfaceMaker object 2112 is activated by passing in the THardwareInterfaceIdentifier 2106 retrieved from the THardwareInterfaceHandle object representing the ACIA port. Elements 2108 and 2110 provide representations of ACIA and 6850, respectively. (2) The TInterfaceMaker object 2112 creates its corresponding service (an access manager 2114) and calls its initializing function, ho, passing in the same THardwareInterfaceIdentifier 2106. This new service is labeled 2114 in FIG. 21 and is an instance of class 2002 in FIG. 20. (3) As shown in FIG. 22, the THardwareinterfaceReference object continues by creating the next TInterfaceMaker object 2200 from the stack description (this is a TUpperInterfaceMaker). It Activates the TUpperInterfaceMaker, passing in the TAccessManagerMaker object it created in step 1. Next comes the tricky part. Knowing full well that the TAccessManagerMaker object 2202 passed into it is an ACIA Maker 2200, it down-casts it to the proper type of maker and asks it for the service 2206 created in step 2. The result of this operation is access to the ACIA Access Manager. Many of the elements of FIG. 22 are identical in nature to corresponding elements of FIG. 21, and need no further explanation. (4) Next, the TUpperInterfaceMaker object creates its corresponding service 2204 (which can be derived from anything), and calls its initializing function, go, passing it the ACIA Access Manager. (5) As shown in FIG. 23, the THardwareInterfaceReference object continues by creating the next TInterfaceMaker object 2300 from the stack description (another TUpperInterfaceMaker). It Activates it, passing in the TAccessManagerMaker object 2302. The down-cast magic happens again (result is the Serial-ACIA service 2306). (6) Finally, the TUpperInterfaceMaker object creates its corresponding service 2304, calls its initializing function, f(), passing it the Serial-ACIA service. Now the service stack is complete. There are no more entries in the stack description. The THardwareInterfaceReference object returns the top-most TInterfaceMaker created in step 5. Clients then down-cast it and gain access to the top-most service in the stack. Create Stack Description--Serial Port (Mouse) Scenario: The Interface Reference framework works when the client isn't real sure about which "top" interface to use. This scenario is slightly different from the previous scenarios because this time the UseConnectorName Class attribute is set to TRUE. This causes the interface reference to use the connector's interface name as the top interface. This is very much like the operations associated with FIG. 15. A client has a TInterfaceReference pointer to an object whose actual subclass is THardwareInterfaceReference and whose top interface is "PointingDevice". The client calls its Activate() method. FIG. 24 is an overview of the hardware configuration for this scenario: the THardwareInterfaceReference object 2408, the mouse's connector 2412, the mouse's HardwareInterfaceIdentifier object 2414, the connection object 2410, the port the mouse is connected to 2402, the port's HardwareInterfaceIdentifier object 2404 and the "metal" 2406. (1) The first step the THardwareInterfaceReference object must perform, in order to create the stack description, is to get the "bottom" interface. This is exactly the same as the previous scenario. (2) The second step is to get the InterfaceName, which is used to specify the "top" interface, from the interface identifier object 2414. This is accomplished by accessing the connector object 2412 and retrieving the identifier object, then calling GetInterfaceName. (3) At this point, we know the top interface "LogiTechMouse" and the bottom interface of our service stack ("6850"). The next step involves searching through the file system looking for the set of services which can be joined to form the required service stack. The top description is tested to ensure that it is a subclass of the class specified by the TopInterface name attribute of the interface reference. (4) FIG. 25 shows the calculated stack "description" 2500 for THardwareInterfaceReference object. Create Stack Description--Serial Port via Switch Box Scenario: The Interface Reference framework works with switch boxes. This scenario demonstrates only the first stage (i.e. creation of the stack description) for a printer connected to the serial port through a switch box. A client has a TInterfaceReference pointer to an object whose actual subclass is THardwareInterfaceReference and whose top interface is set to "Printer". The client calls its Activate() method. FIG. 26 is an overview of the hardware configuration for this scenario: the THardwareInterfaceReference object 2600, the printer's connector 2602 (an attribute of the THardwareInterfaceReference object), the printer's HardwareInterfaceIdentifier object 2604 a connection object 2606, a connector on the switch box 2608, a switch box connector's HardwareInterfaceIdentifier object 2610, the switch box's default connector 2612, a connection object 2614, and the port the switch box is connected to 2616. (1) The first step the THardwareInterfaceReference object must perform, in order to create the stack description, is to get the "bottom" interface. It does this by navigating across THardwareInterfaceHandle objects until it finds a THardwareInterfaceIdentifier object which can be activated. Although FIG. 26 looks complicated, it really isn't. The process is a simple repetition of the earlier scenario involving a straight serial port. The bottom interface is found as follows. First, access the THardwareInterfaceReference object's connector attribute 2602. Next, retrieve the HardwareInterfaceldentifier object 2604 and test it. It can not be activated, so we continue. Next, we retrieve the connection object 2606 from the printer's connector. The switch box Hardwarelnterface object 2608 is retrieved from the connection object. The HardwareInterfaceldentifier object retrieved can not be activated. We have now completed one full pass through a THardwareConnectionHandle object, but did not find an interface identifier which could be activated. What we must do now is create a service which can represent the device we got stuck on, element 2608. If a service can not be created for this device, then we fail. The device can be an automatic or a manual switch box. An automatic switch box requires a service which can control the switch box. A manual switch box requires a service also, only to be consistent. To create this service, we create a THardwareInterfaceReference on the switch box's default THardwareInterfaceHandle object 2612. We set the top interface to MMultiplexer (or something appropriate we can define later). Next, we Activate it. This results in the continuation of the search for a "bottom" interface. It follows the connection object 2614 and ends up at the THardwareInterfaceHandle object 2616, which IS activatable. A valid bottom has been found. The interface reference we created continues by creating a service stack for the switch box (note: this is not the service stack the client is interested in, we just got temporarily side tracked because of the switch box). At this point, we have a service which is an MMultiplexer. Developers of automatic switch boxes will have to supply this service themselves. For manual switch boxes, we can provide our own standard service which works for all manual switch boxes. We call Switch() on MMultiplexer, passing in the connector to switch to (i.e. 2608). The Switch method has the responsibility of setting the multiplexer to our connector (only if it's automatic). If it's a manual switch box, the user has the responsibility to push the proper button. If it is a manual switch box, a user alert could be optionally generated to remind the user to push the button on the manual switch box. This alert is only required when the serial port is accessing a different device from the previous activation (i.e., if we are activating for the modem a second time in a row, then the user doesn't need to do anything). At this point, we can assume that the switch box has been switched to the appropriate position. We get the "bottom" interface from the MMultiplexer and delete the MMultiplexer service stack. We no longer need it. We only used it to get the bottom interface and to perform the switch. We now have the proper bottom interface from which to construct the client's service stack. Create Stack Description--SCSI Device Scenario: The Interface Reference framework works for auto-configurable devices too. This scenario demonstrates the first stage (i.e. creation of the stack description) for a printer connected to the SCSI port. In this example, the client wants to talk to the SCSI device, not the port. A different scenario is possible, which would create a service stack for the port. The computer viewer does this when the user asks it to refresh the SCSI port. A client has a TInterfaceReference pointer to an object whose actual subclass is THardwareInterfaceReference and whose top interface is set to "Printer". The client calls its Activate() method. FIG. 27 is an overview of the hardware configuration for this scenario: the THardwareInterfaceReference object 2700, the printer's connector 2702 (an attribute of the THardwareInterfaceReference object), and the printer's HardwareInterfaceIdentifier object 2704. (1) The first step the THardwareInterfaceReference object must perform, in order to create the stack description, is to get the "bottom" interface. It does this by navigating across THardwareInterfaceHaindle objects until it finds a THardwareInterfaceIdentifier object which can be activated. The bottom interface is found by accessing the THardwareInterfaceReference object's connector attribute 2702. Then the THardwareInterfaceIdentifier object 2704 is retrieved from it. Next, the HardwareInterfaceldentifier object is tested. Since it can be activated, we are done. The ID specifies "SCSI" as the Bottom Interface. (2) At this point, we know the very Top and the very Bottom interface of our service stack. The next step involves searching through the file system looking for the set of services which can be joined to form the required service stack. Note: The SCSI interface identifier is passed into the bottom service. The SCSI identifier contains a SCSI device handle which the bottom service can get and use to talk to the SCSI printer. Activate a TNetworkInterfaceReference Scenario: For a TNetworkInterfaceReference object whose "Top Interface" is set to "Printer", a client calls its Activate() method. Activation occurs in two stages: (I) Creation of the stack description and (II) creation of the stack (I) Creation of the stack description (1) The first step the TNetworkReference object must perform in order to create the stack description is to set the "bottom" interface to "MessageStream". (2) At this point, we know the very Top and the very Bottom interface of our service stack. The rest of this stage plays out exactly like THardwareInterfaceReference. (II) Creation of the stack The TNetworkReference object creates the stack in the following order: The TNetworkReference object creates the bottom most TInterfaceMaker object in the stack description (a TNetworkMaker object). The TNetworkReference object activates it, passing in the TServiceReference object. The TInterfaceMaker object creates its corresponding service (can be derived from anything). The TInterfaceMaker object calls its initializing function f(), passing in the same TServiceReference. Network service stacks can be deeper than one level. Instantiate a THardwareInterfaceReference Scenario: The computer viewer has a THardwareModuleHandle object and has created its corresponding model object. Now it is ready to create and add THardwareInterfaceReference objects f() the model, one for each THardwareInterfaceHandle object owned by the THardwareModuleHandle object. (1) First, it creates an iterator for the THardwareInterfaceHandle objects (i.e. connectors) in the THardwareModuleHandle object. (2) Next, for each THardwareInterfaceHandle object returned by the iterator, it creates and adds a THardwareInterfaceReference object to the model as follows: theModel.AddlnterfaceReference(THardwareInterfaceReference(aHardwarelnt erface)); Instantiate a TNetworkInterfaceReference Scenario: Network Browser issue. Use a Manually Connected Device (configured via "Let Resources Find You") Scenario: A user prints a document using a printer connected to the local serial port. This scenario illustrates an example of how THardwareInterfaceReference can be used by the printer framework for an ImageWriterII. FIG. 28 illustrates the scenario. (1) A user drags a document icon onto an ImageWriter icon. (2) The printer icon accepts the document icon. The document and the printer collaborate resulting in the creation of a print job which is added to the TPrinter object 2802 representing the ImageWriter. (3) The PrinterHandler object 2804 calls Activate on the THardwareInterfaceReference object 2806 which was passed down from the TPrinter object 2802. (4) The THardwareInterfaceReference object creates the appropriate service stack and returns a reference to it. Use a Manually Connected Device (configured via "You find the Resource") Scenario: Someone wants to query the computer hardware database for an ImageWriter and access it. (1) Search the computer hardware database for the THardwareModuleHandle object which has "AppleImageWriterII" as its signature. (2) Get the proper THardwareInterfaceHandle object from the THardwareModuleHandle object. (3) Create a THardwareInterfaceReference, passing in the THardwareInterfaceHandle object. (4) Set the top interface of the THardwareInterfaceReference object. (5) Activate the reference object and begin communication with the ImageWriter II. Change a Connection of a Manually Connected Device Scenario: This scenario demonstrates that a document, whose default printer is a particular local ImageWriter, maintains its ability to print to that printer even after the user has changed the printer's connection. Please refer to the "Low-Level Hardware Configuration ERS" for this scenario. 3.3.12 Developer creates a new service Scenario: Show the classes necessary to introduce two new services into Pink, using the mechanism defined in this ERS. The new services are: UART service for a TxyzUART and a UART service for a TpdqUART. (1) FIG. 29 illustrates Maker Class diagrams. (2) FIG. 30 illustrates Service Class diagrams. Note: there is a one-to-one correspondence between the maker classes and the service classes. The shaded classes are written by the developer. Class Interfaces TInterfaceReference Class Description Purpose: Please refer to the above discussion for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: An instance of a subclass of TInterfaceReference may be saved to a file and restored at any time. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TInterfaceReference
public:
/ /.....................................
/ / Standard methods
virtual void GetTopInterface(InterfaceName&) const;
virtual void SetTopInterface(const InterfaceName&);
virtual void GetBundles(TDictionary<InterfaceName,
TInterfaceBundle>&) const;
virtual void SetBundles(const TDictionary<InterfaceName,
TInterfaceBundle>&);
virtual void GetPossibleTops(TCollection<InterfaceName>&) const;
virtual TInterfaceMaker* Activate() = 0;
/ /.......................................
/ / Special Operators
virtual TStream& operator>>=(TStream& toWhere) const;
virtual TStream& operator>>=(TStream& fromWhere);
virtual .about.TInterfaceReference();
protected:
/ /.......................................
/ / Constructors
TInterfaceReference();
TInterfaceReference(const TInterfaceReference& copyFrom);
TInterfaceReference& operator=(const TInterfaceReference&
copyFrom);
private:
};
#endif
______________________________________
Member Functions void GetTopInterface(InterfaceName&) const Gets the top interface of this InterfaceReference. Clients will rarely call this method. void SetTopInterface(const InterfaceName&) This method specifies the interface of the service that you want Activate to return. Clients must call this method sometime before they call Activate. void GetBundles(TDictionary<InterfaceName,TInterfaceBundle>&) Fills up the collection argument with all of the TInterfaceBundle objects in this InterfaceReference. Does not empty the dictionary first. Clients will rarely call this method. void SetBundles(const TDictionary<InterfaceName,TInterfaceBundle>&) Deletes the current Bundles attribute in this InterfaceReference, then copies (clones) the given TDictionary ›13! object and makes it the new Bundles attribute. Subsequent activations of this InterfaceReference use the new Bundles attribute. Clients call this method if the services they activate require service specific data. See the activate methods of the maker subclasses for more details. void GetPossibleTops(TCollection<InterfaceName>&) Fills up the collection argument with all of the InterfaceName objects that this InterfaceReference can currently support, given the current "installed" services on the system. Each InterfaceName object in the collection identifies one type of supported service. Clients may call this method to determine what services are available for a given InterfaceReference. The computer viewer uses this method during type negotiation between connectors. For example, a user attempting to connect an ImageWriter to a SCSI port will be prevented from doing so if the InterfaceReference does not say serial is supported by the SCSI port. TInterfaceMaker Activate() =0 This method creates a service stack whose top service has an interface specified by SetToplnterfaceo. The bottom resource is subclass dependent. It could be a hardware component, a network service or a software service. This method is called directly by clients. A pointer to a TInterfaceMaker object, of the specified type, is returned. Clients down-cast this pointer to the appropriate type and get a pointer to the real service object. After this has been done, the client is required to delete the TInterfaceMaker object. TStream& operator>>=(TStream& toWhere) const Streams out the entire interface reference object into the toWhere argument. TStream& operator<<=(TStream& fromWhere) Streams in the entire interface reference object from the fromWhere argument. .about.THardwareInterfaceReference() Destroys the interface reference object only. It does not affect the activated service(s), if any. THardwareInterfaceReference() Subclasses may call to create an empty THardwareInterfaceReference object. THardwareInterfaceReference(const THardwareInterfaceReference& copyFrom) Subclasses call (copy constructor). THardwareInterfaceReference& operator=(const THardwareInterfaceReference& copyFrom) Subclasses call. Network Interface Reference Class Description Purpose: Please refer to section 3.2 for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: An instance of a TNetworkInterfaceReference may be saved to a file and restored at any time. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TNetworkInterfaceReference : public TInterfaceReference
public:
/ /...................................
/ / Constructors & Destructor
TNetworkInterfaceReference();
TNetworkInterfaceReference(const TServiceReference&);
virtual .about.TNetworkInterfaceReference();
TNetworkInterfaceReference(const TNetworkInterfaceReference&
copyFrom);
TNetworkInterfaceReference& operator=(const
TNetworkInterfaceReference&
copyFrom);
/ /...................................
/ / Standard methods
virtual TServiceReference* CreateServiceReference() const;
virtual void SetServiceReference(const TServiceReference&);
/ /...................................
/ / Overrides
virtual TInterfaceMaker* Activate();
virtual TStream& operator>>=(TStream& toWhere) const;
virtual TStream& operator<<=(TStream& fromWhere);
protected:
private:
};
#endif
______________________________________
Member Functions TNetworkInterfaceReference() Creates a default interface reference for a service connected to a network. The object must be given a "top" interface name and a service reference before Activate is called, or else an exception will be generated. Useful for streaming. TNetworkInterfaceReference(const TServiceReference&) Creates an interface reference for a service connected to a network and is represented by the given service reference object. The object must be given a "top" interface name before Activate is called, or else an exception will be generated. .about.TNetworkInterfaceReference() Destroys this interface reference object; but does not affect the activated service(s), if any. TNetworkInterfaceReference(const TNetworkInterfaceReference& copyFrom) Copies the entire interface reference object from the copyFrom argument into this object. TNetworkInterfaceReference& operator=(const TNetworkInterfaceReference& copyFrom) Copies the entire interface reference object from the copyFrom argument into this object. TServiceReference CreateServiceReference() const Creates and returns a copy of the Service Reference attribute in this NetworkInterfaceReference. Client adopts returned object. Clients are not expected to use this method.sup.1. void SetServiceReference(const TServiceReference&) Sets the Service Reference attribute in this NetworkInterfaceReference. Creators of NetworkInterfaceReference objects use this method to specify the network service providing the service. TInterfaceMaker Activate() This method creates a service stack for an entity on a network, whose top service has an interface specified by SetToplnterface(). This method is called directly by clients. A pointer to a TInterfaceMaker object, of the specified type, is returned. Clients down-cast this pointer to the appropriate type and get a pointer to the real service object. After this has been done, the client is required to delete the TInterfaceMaker object. TStream& operator>>=(TStream& toWhere) const Streams out the entire interface reference object into the toWhere argument. TStream& operator<<=(TStream& fromWhere) Streams in the entire interface reference object from the fromWhere argument. THardwareInterfaceReference Class Description Purpose:Please refer to section 3.2 for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: An instance of a THardwareInterfaceReference may be saved to a file and restored at any time.
______________________________________
#ifndef NO.sub.-- SPI
class THardwareInterfaceReference : public TInterfaceReference
public:
/ /...................................
/ / Constructors & Destructor
THardwareInterfaceReference();
THardwareInterfaceReference(const THardwareInterfaceHandle&);
THardwareInterfaceReference(const THardwareInterfaceIdentifier&);
virtual .about.THardwareInterfaceReference();
THardwareInterfaceReference(const THardwareInterfaceReference&
copyFrom);
THardwareInterfaceReference& operator=(const
THardwareInterfaceReference&
copyFrom);
/ /...................................
/ / Standard methods
virtual void SetTopInterface(const InterfaceName&,
Boolean useConnectorName);
virtual THardwareInterfaceHandle GetConnector() const;
virtual void SetConnector(const THardwareInterfaceHandle&);
/ /...................................
/ / Overrides
virtual void SetTopInterface(const InterfaceName&); // c++
syntax requireme:
virtual TInterfaceMaker* Activate();
virtual TStream& operator>>=(TStream& toWhere) const;
virtual TStream& operator<<=(TStream& fromWhere);
protected:
private:
};
#endif
______________________________________
Member Functions THardwareInterfaceReference() Creates a default interface reference for a service provided by a device connected to a local computer. The object must be given a "top" interface name and a THardwareInterfaceHandle before Activate is called, or else an exception will be generated. Useful for streaming. THardwareInterfaceReference(const THardwareInterfaceHandle&) Creates an interface reference for a service provided by a device connected to a local computer. The device is identified by the given hardware interface handle. The object must be given a "top" interface name before Activate is called, or else an exception will be generated. THardwareInterfaceReference(const THardwareInterfaceIdentifier&) Creates an interface reference for a service provided by a device connected to a local computer. The device is identified by the given hardware interface identifier. The object must be given a "top" interface name before Activate is called, or else an exception will be generated. .about.THardwareInterfaceReference () Destroys this interface reference object, but does not affect the activated service(s), if any. THardwareInterfaceReference(const THardwareInterfaceReference& copyFrom) Copies the entire interface reference object from the copyFrom argument into this object. THardwareInterfaceReference& operator=(const THardwareInterfaceReference& copyFrom) Copies the entire interface reference object from the copyFrom argument into this object. void SetToplnterface(const InterfaceName&, Boolean UseConnectorName) This method specifies the interface of the top service object that you want Activate to return. If the UseConnectorName argument is TRUE, then the top InterfaceName argument will be treated as a base class name (for type checking) and the real "top" interface name of the service stack will be retrieved from the connector. If the UseConnectorName argument is FALSE, then this method behaves as the normal SetToplnterface method. THardwareInterfaceHandle GetConnector() const Returns a copy of the Connector attribute in this HardwareInterfaceReference. The Connector attribute represents the connector on the physical hardware which actually provides the service (e.g. the connector on the back of a StyleWriter). This connector is connected to a port which drives the service (e.g. the serial port on a PC motherboard). Clients will rarely, if ever, use this method. HardwareInterfaceReference uses it to determine the bottom interface. void SetConnector(const THardwareInterfaceHandle&) Sets the Connector attribute in this HardwareInterfaceReference. Creators of HardwareInterfaceReference objects use this method to specify the connector on the physical hardware which actually provides the service (e.g. the connector on the back of a StyleWriter). TInterfaceMaker Activate() This method creates a service stack for a device connected to a local computer, whose top service has an interface specified by SetToplnterface( ). This method is called directly by clients. A pointer to a TInterfaceMaker object, of the specified type, is returned. Clients down-cast this pointer to the appropriate type and get a pointer to the real service object. After this has been done, the client is required to delete the TInterfaceMaker object. TStream& operator>>=(TStream& toWhere) const Streams out the entire interface reference object into the toWhere argument. TStream& operator<<=(TStream& fromWhere) Streams in the entire interface reference object from the fromWhere argument. TInterfaceMaker Class Description Purpose: Please refer to section 3.2 for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: Interface Makers are not persistent. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TInterfaceMaker
public:
/ /...................................
/ / Destructor
virtual .about.TInterfaceMaker();
protected:
/ /...................................
/ / Constructors
TInterfaceMaker();
TInterfaceMaker(const TInterfaceMaker& copyFrom);
TInterfaceMaker& operator=(const TInterfaceMaker& copyFrom);
private:
};
#endif
______________________________________
Member Functions .about.TInterfaceMaker() Destroys this interface maker object. TInterfaceMaker() Creates a default interface maker for an interface maker subclass. TInterfaceMaker(const TInterfaceMaker& copyFrom) Copies the entire interface maker object from the copyFrom argument into this object. TInterfaceMaker& operator=(const TInterfaceMaker& copyFrom) Copies the entire interface maker object from the copyFrom argument into this object. TUpperInterfaceMaker Class Description Purpose: Please refer to section 3.2 for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: Interface Makers are not persistent. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TUpperInterfaceMaker : public TInterfaceMaker
public:
/ /...................................
/ / Standard methods
virtual void Activate(const TInterfaceMaker& below, const
TInterfaceBundle&) = 0;
/ /...................................
/ / Destructor
virtual .about.TUpperInterfaceMaker();
protected:
/ /...................................
/ / Constructors
TUpperInterfaceMaker();
TUpperInterfaceMaker(const TUpperInterfaceMaker& copyFrom);
TUpperInterfaceMaker& operator=(const TUpperInterfaceMaker&
copyFrom);
private:
};
#endif
______________________________________
Member Functions virtual void Activate(const TInterfaceMaker& below, const TInterfaceBundle&)=0 Subclasses know what "real" service object to make. This method is called by a TInterfaceReference object, passing in the below interface maker object. The subclass down-casts it and asks it for the real below service. The real below service is then given to the service object created by the interface maker subclass. If the TInterfaceReference object has a TInterfaceBundle associated with the top interface corresponding to this maker, then the TInterfaceReference object will pass it into this function. If the given TInterfaceBundle pointer is not nil, then the callee can safely down-cast it to the type it expects. This object contains special service specific information (e.g. BAUD rate). .about.TUpperInterfaceMaker() Destroys this interface maker object. TUpperInterfaceMaker() Creates a default interface maker for an upper interface maker subclass. TUpperInterfaceMaker(const TUpperInterfaceMaker& copyFrom) Copies the entire interface maker object from the copyFrom argument into this object. TUpperInterfaceMaker& operator=(const TUpperInterfaceMaker& copyFrom) Copies the entire interface maker object from the copyFrom argument into this object. TAccessManagerMaker Class Description Purpose: Please refer to the above discussion for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: Interface Makers are not persistent. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TAccessManagerMaker : public TInterfaceMaker
{;
public:
/ /....................................
/ / Standard methods
virtual void Activate(const THardwareInterfaceIdentifier& theMetal,
const TInterfaceBundle&) =0;
/ /...................................
/ / Destructor
virtual .about.TAccessManagerMaker();
protected:
/ /...................................
/ / Constructors
TAccessManagerMaker();
TAccessManagerMaker(const TAccessManagerMaker& copyFrom);
TAccessManagerMaker& operator=(const TAccessManagerMaker&
copyFrom);
private:
};
#endif
______________________________________
Member Functions virtual void Activate(const THardwareInterfaceIdentifier& theMetal, const TInterfaceBundle&)=0 Subclasses know what "real" Access Manager object to make. This method is called by a TInterfaceReference object, passing in the THardwareInterfaceIdentifier object. This is given to the AccessManager object created by the AccessManagerMaker subclass. The bundle parameter follows the same rules as specified for TUpperInterfaceMaker::Activate. .about.TAccessManagerMaker() Destroys this access manager maker object. TAccessManagerMaker() Creates a default access manager maker for an upper interface maker subclass. TAccessManagerMaker(const TAccessManagerMaker& copyFrom) Copies the entire access manager maker object from the copyFrom argument into this object. TAccessManagerMaker& operator=(const TAccessManagerMaker& copyFrom) Copies the entire access manager maker object from the copyFrom argument into this object. TInterfaceBundle Class Description Purpose: Please refer to the discussion above for the purpose of this class, what an instance of this class represents, what this class is used for and the meaning of its attributes. Deriving Classes: This class is polymorphic. Concurrency: This class is not multi-thread safe. Persistence: Interface Bundles are persistent. Interface:
______________________________________
#ifndef NO.sub.-- SPI
class TInterfaceBundle
public:
/ /....................................
/ / Destructor
virtual .about.TInterfaceBundle();
/ /....................................
/ / Special Operators
virtual TStream& operator>>=(TStream& toWhere) const;
virtual TStream& operator<<=(TStream& fromwhere);
protected:
/ /....................................
/ / Constructors
TInterfaceBundle();
TInterfaceBundle(const TInterfaceBundle& copyFrom);
TInterfaceBundle& operator=(const TInterfaceBundle& copyFrom);
private:
};
#endif
______________________________________
Member Functions .about.TInterfaceBundle() Destroys this interface bundle object. TInterfaceBundle() Creates a default interface bundle for an interface bundle subclass. TStream& operator>>=(TStream& toWhere) const Streams out the entire interface bundle object into the toWhere argument. TStream& operator<<=(TStream& fromWhere) Streams in the entire interface bundle object from the fromWhere argument. TInterfaceBundle(const TInterfaceBundle& copyFrom) Copies the entire interface bundle object from the copyFrom argument into this object. TInterfaceBundle& operator=(const TInterfaceBundle& copyFrom) Copies the entire interface bundle object from the copyFrom argument into this object. It is possible that more than one stack description may be generated during an Activate. There are multiple paths through the sea of service stacks which can adequately provide the requested top service on the desired device ID. Some heuristic will resolve and select one stack. Clients, for example time-based media, may be very interested in the middle layers for the various stack choices. Characteristics of these layers may need to be figured into the equation and preferences solicited for use in the selection. If a mouse device is not registered (related to the dead mouse issue), there must be the ability to create a driver for the mouse. Two possible solutions: (1) Register mouse device, Activate the reference, Unregister the mouse. (2) CAM creates the driver when it detects the mouse moving. It may be desirable to delay creation of a service until the point where it is required. For example, delaying the creation of a printer service for an ImageWriter, until the point that a user drags a document orito the printer. Or, the service could be created immediately upon discovery that an ImageWriter is connected. The preferred embodiment allows clients to make either choice. Setting the BAUD rate for a serial ImageWriter is performed by storing service specific parameters in bundles stored in a TDictionary stored in the model. They copy the dictionary into their TInterfaceReference when they get it. Design Decisions--Interface Maker When clients first look at the TInterfaceReference class, they see an abstraction which is capable of creating and returning a particular type of service. Unfortunately, TInterfaceReference obscures what is seemingly a simple and commonplace operation by introducing a maker class. The affect on the client, is the addition of an extra step in order to access the service stack. Developers are burdened with extra implementation effort by being forced to code the maker class. Everyone is burdened with the extra mental effort required to understand the design. There are reasons for having to deal with the extraneous maker classes, but there are several issues which must be discussed in order to obtain a full understanding of extraneous maker classes. First, we need to examine closely the hierarchy of TPresentableViews 3102, as shown in FIG. 31. TPresentableView 3102 is a subclass of TView 3100. TPresentableView 3102 is used to represent many views throughout the system (e.g. controls, editable text, grid views, interactive views, movies, panes, etc., shown collectively as 3104). There is a common abstraction among all view objects (e.g. drawing, transformations, notification, hit tests, nesting other views, etc.). This suggests a common base abstraction. Furthermore, views are used throughout much of the user interface system, which suggests a need for polymorphism. Now, lets examine service stacks. As stated above, it is desirable to avoid a common class hierarchy for services. If we rejected this goal, the service hierarchy would be required to look as shown in FIG. 32. There is no commonality between a disk driver associated with 3206, a serial port driver associated with 3208 a Printer associated with 3204, or a mouse driver associated with 3202. There is no requirement for polymorphism. Service stacks are not going to be passed around to various parts of the system. All polymorphic requirements are handled by the TInterfaceReference class. So, the advantages of requiring a common abstraction where none exists conceptually do not appear to out weigh the disadvantages. There is actually a positive side to the maker classes. Any service can be supported by the interface reference framework via the introduction of a maker. For example, if a service were created which was not expected to be used by an interface reference, a developer would not be prevented from using the service in a service stack. All the developer is required to do is write one maker class (much less work than writing the service from scratch or writing a wrapper). A wrapper would be required if there were no maker classes. This would imply that all services would have to derive from TService 3200. Since the class in question did not, the developer would wrap up the class in a TService derivative. FIG. 33 illustrates how easy it is for a developer to make any service work within the interface reference framework by adding one maker class. The disk drive service is not supported by the interface reference framework (at the time, no one thought it was necessary). In FIG. 34, however, the disk drive service is NOW supported by the interface reference framework (someone had a need, and a maker was developed). While the invention has been described in terms of a preferred embodiment in a specific system environment, those skilled in the art recognize that the invention can be practiced, with modification, in other and different hardware and software environments within the spirit and scope of the appended claims.
|
Same subclass Same class Consider this |
||||||||||
