Universität Ulm, Fakultät für Mathematik und Wirtschaftswissenschaften, SAI

WS 97/98 || Entwicklung objekt-orientierter Bibliotheken || Beispiele || Collections-13

MODULE Collections


MODULE Collections;

   IMPORT Disciplines, Events, RelatedEvents;

   TYPE
      Collection = POINTER TO CollectionRec;

   (* Schnittstelle fuer Implementierungen *)

   TYPE
      Message = RECORD END;
      AddProc = PROCEDURE (collection: Collection; object: Disciplines.Object);
      FirstProc = PROCEDURE (collection: Collection);
      NextProc = PROCEDURE (collection: Collection;
			    VAR object: Disciplines.Object) : BOOLEAN;
      GetProc = PROCEDURE (collection: Collection;
			   index: INTEGER; VAR object: Disciplines.Object);
      RemoveProc = PROCEDURE (collection: Collection;
			      object: Disciplines.Object) : BOOLEAN;
      HandlerProc = PROCEDURE (collection: Collection;
			       VAR message: Message);
      Interface = POINTER TO InterfaceRec;
      InterfaceRec =
	 RECORD
	    add: AddProc;         (* required *)
	    first: FirstProc;     (* required *)
	    next: NextProc;       (* required *)
	    get: GetProc;         (* optional *)
	    remove: RemoveProc;   (* optional *)
	    handler: HandlerProc; (* optional *)
	 END;

   CONST
      get = 0; remove = 1; handler = 2;
   TYPE
      Capability = SHORTINT; (* get..handler *)
      CapabilitySet = SET; (* OF Capability *)

   TYPE
      CollectionRec =
	 RECORD
	    (Disciplines.ObjectRec)
	    (* private Komponenten *)
	    if: Interface;
	    caps: CapabilitySet;
	 END;

   (* error handling *)

   CONST
      objectNotInCollection = 0;
	 (* Collections.Remove failed because
	    the object is not in the collection
	 *)
      badIndex = 1;
	 (* Collections.Get failed because of an invalid index *)
      errors = 2;
   TYPE
      ErrorCode = SHORTINT;
      ErrorEvent = POINTER TO ErrorEventRec;
      ErrorEventRec =
	 RECORD
	    (Events.EventRec)
	    errorcode: ErrorCode; (* what happened...? *)
	    collection: Collections.Collection;
	       (* failed operation was called for this collection *)
	    object: Disciplines.Object;
	       (* the parameter, if present (may be NIL otherwise) *)
	 END;
   VAR
      error: Events.EventType;
      errormsg: ARRAY errors OF Events.Message;
	 (* error message texts for all error codes returned by this module *)

   PROCEDURE InitErrorHandling;
   BEGIN
      Events.Define(error);
      errormsg[objectNotInCollection] :=
	 "object is not member of the collection";
      errormsg[badIndex] := "invalid index";
   END InitErrorHandling;

   PROCEDURE Error(collection: Collection;
		   object: Disciplines.Object; (* may be NIL *)
		   errorcode: ErrorCode);
      VAR
	 event: ErrorEvent;
   BEGIN
      NEW(event);
      event.type := error;
      event.message := errormsg[errorcode];
      event.errorcode := errorcode;
      event.collection := collection;
      event.object := object;
      RelatedEvents.Raise(collection, event);
   END Error;

   PROCEDURE Init(collection: Collection; if: Interface; caps: CapabilitySet);
   BEGIN
      ASSERT((if.add # NIL) & (if.first # NIL) & (if.next # NIL));
      ASSERT(~(get IN caps) OR (if.get # NIL));
      ASSERT(~(handler IN caps) OR (if.handler # NIL));
      collection.if := if;
      collection.caps := caps;
   END Init;

   PROCEDURE Send(collection: Collection; VAR message: Message);
   BEGIN
      ASSERT(handler IN collection.caps);
      collection.if.handler(collection, message);
   END Send;

   (* Schnittstelle fuer Klienten *)

   PROCEDURE Capabilities(collection: Collection) : CapabilitySet;
   BEGIN
      RETURN collection.caps
   END Capabilities;

   PROCEDURE Add(collection: Collection; object: Disciplines.Object);
   BEGIN
      collection.if.add(collection, object);
   END Add;

   PROCEDURE First(collection: Collection);
   BEGIN
      collection.if.first(collection);
   END First;

   PROCEDURE Next(collection: Collection;
		  VAR object: Disciplines.Object) : BOOLEAN;
   BEGIN
      RETURN collection.if.next(collection, object)
   END Next;

   PROCEDURE Get(collection: Collection;
		 index: INTEGER; VAR object: Disciplines.Object);
   BEGIN
      ASSERT(get IN collection.caps);
      collection.if.get(collection, index, object);
      IF object = NIL THEN
	 Error(collection, NIL, badIndex);
      END;
   END Get;

   PROCEDURE Remove(collection: Collection; object: Disciplines.Object);
      (* wird nicht von allen Implementierungen unterstuetzt *)
   BEGIN
      ASSERT(remove IN collection.caps);
      IF ~collection.if.remove(collection, object) THEN
	 Error(collection, object, objectNotInCollection);
      END;
   END Remove;

BEGIN
   InitErrorHandling;
END Collections.

WS 97/98 || Entwicklung objekt-orientierter Bibliotheken || Beispiele || Collections-13

Andreas Borchert, 6. Dezember 1997