The current software architecture of ColdFrame uses Ada 2005 Containers, which provide various ways of handling groups of things in containers.
In ColdFrame, for each non-«singleton» Class, there's a private means of holding all the current Instances of the class, together with public interfaces allowing the creation, finding, accessing and eventual deletion of instances.
As well as this, there is public support for obtaining and handling vectors (collections) of instances.
The container types used by generated code are
In all cases the actual things contained (the "Element_Type"s) are Handles, ie pointers to instances of the class concerned. Allocation of instances is handled within the class's Create function, and deallocation in Delete.
Stubs use Maps, Sets, and Vectors.
Given the domain Domain and the class Class, the standard public Component instantiation (in the package Domain.Class) is the package Domain.Class.Vectors, an instantiation of Ada.Containers.Vectors (or Bounded_Vectors) using Domain.Class.Handle.
ColdFrame provides three utility functions for dealing with variables of type Domain.Class.Vectors.Vector, as child subprograms of Domain.Class (note, this means they have to be withed individually):
function Domain.Class.All_Instances return Domain.Class.Vectors.Vector;
generic with function Pass (This : Handle) return Boolean is <>; function Domain.Class.Filter_Function (The_Vector : Domain.Class.Vectors.Vector) return Domain.Class.Vectors.Vector;
generic with function Pass (This : Handle) return Boolean is <>; function Domain.Class.Selection_Function return Domain.Class.Vectors.Vector;
For each Class, ColdFrame generates a generic procedure Domain.Class.Iterate; it can be easier to use this than to use the Containers' iteration facilities directly. Also, direct use means that your code is more closely tied than it need be to the current ColdFrame implementation strategy.
If you do need to use Container iteration, there are two forms: open and closed (Ada 2012 adds a third, much simpler, form).
With open iteration, you create an iterator or Cursor designating the first element of the container; while the cursor designates a valid element you process the element, then advance the cursor to the next element in the container it references. With closed iteration, you supply a procedure which gets called for each element in the container.
The operations on Cursors are all defined in Domain.Class.Vectors.
The examples below are in terms of a pre-existing container The_Vector. You may take exception to the overloading of the name Process!
declare It : Class.Vectors.Cursor := The_Vector.First; use type Class.Vectors.Cursor; begin while It /= Class.Vectors.No_Element loop declare H : Class.Handle := Class.Vectors.Element (It); begin -- do something with H end; Class.Vectors.Next (It); end loop; end;
for H of The_Vector loop -- do something with H end loop;
declare procedure Process (C : Class.Vectors.Cursor) is begin -- do something with Class.Vectors.Element (C) end Process; begin The_Vector.Iterate (Process'Access); end;
declare procedure Process (H : Class.Handle); pragma Inline_Always (Process); procedure Process is new Class.Iterate (Process); procedure Process (H : Class.Handle) is begin -- do something with H end Process; begin Process (The_Vector); end;
Most filtering requirements should be met by the generated Filter_Function and Selection_Function generics.
The Ada Container Vectors provide a generic sorting facility in Domain.Class.Vectors.Generic_Sort.
The resulting ordering is in terms of the function that instantiates the parameter "<"; the Element that is "less than" all the other Elements in the Vector will end up first. The sort should not be expected to be stable; that is, don't expect Elements which compare "=" to remain in the same order.
An example of sorting by threateningness, assuming the existence of Candidate_Tracks of type Track.Vectors.Vector, is
declare function Is_More_Threatening (L, R : Track.Handle) return Boolean; package Sorting is new Track.Vectors.Generic_Sort ("<" => Is_More_Threatening); function Is_More_Threatening (L, R : Track.Handle) return Boolean is begin return L.Time_Of_CPA < R.Time_Of_CPA; end Is_More_Threatening; begin Sorting.Sort (Candidate_Tracks); end;after which Candidate_Tracks.First_Element will return the track with the earliest Time_Of_CPA (CPA means Closest Point of Approach).