-- This package provides a set abstraction built on top of the "Object.
-- Handle" and "Object.Iterator" abstractions of the "Directory_Tools"
-- package. Standard set operations such as union and intersection are
-- provided. In addition, operations are provided to create sets based
-- on relationships between compilation units.
--
-- Since the underlying representation of an object set is the same as
-- an object iterator, operations from the "Directory_Tools" package may
-- be freely applied to object sets, and vice versa.
--
-- This package has a renaming package "Object_Sets_Renames" associated
-- with it which allows the algebraic set operations defined in this
-- package to be written as infix operators.
--
-- Most operations in this package need to read more than one object
-- during execution. No synchronization is used by these operations: they
-- process only one object in a set at a time. This allows other users
-- to access objects in a set while the set is being processed without a
-- lock error occurring. There is the possibility, however, that another
-- user's access will partially invalidate the results of an operation,
-- and this needs to be taken into account.
--
with Activity;  
with Directory_Tools;
package Object_Sets is

    subtype Element is Directory_Tools.Object.Handle;
    subtype Set is Directory_Tools.Object.Iterator;

    function Empty_Set return Set;
    --
    -- Returns a new set which contains no elements.

    function Is_Empty (This_Set : in Set) return Boolean;

    function Number_In (This_Set : in Set) return Natural;

    function Are_Equal (This_Set : in Set; That_Set : in Set) return Boolean;
    --
    -- Returns True if the sets contain exactly the same elements.

    function Copy_Of (This_Set : in Set) return Set;

    function Is_Member
                (This_Set : in Set; This_Element : in Element) return Boolean;

    procedure Add (This_Element : in Element; This_Set : in out Set);
    --
    -- Adds the element to the set. Does nothing if the element is already
    -- in the set.

    procedure Remove (This_Element : in Element; This_Set : in out Set);
    --
    -- Removes the element from the set. Does nothing if the element is not
    -- in the set.

    generic

        with function "<" (This_Element : in Element; That_Element : in Element)
                          return Boolean;

    procedure Sort (This_Set : in out Set);
    --
    -- Sorts the elements in the specified set in accordance with the supplied
    -- "<" function.

    generic

        with function Dont_Want (This_Element : in Element) return Boolean;

    procedure Filter (This_Set : in out Set);
    --
    -- Removes elements from the specified set in accordance with the supplied
    -- function "Dont_Want".

    generic

        with procedure Process (This_Element : in out Element);

    procedure Process_Elements (This_Set : in out Set);
    --
    -- Applies the supplied processing procedure to all elements in the
    -- specified set.

    generic

        type Process_State is private;

        with procedure Initialize (This_State : in out Process_State);

        with procedure Process (This_Element : in out Element;
                                This_State : in out Process_State);

        with procedure Finalize (This_State : in out Process_State);

    procedure Process_Elements_With_State
                 (This_Set : in out Set; This_State : in out Process_State);
    --
    -- Applies the supplied processing procedure to all elements in the
    -- specified set while preserving state information in a state variable
    -- controlled by the client.


    -- ALGEBRAIC OPERATIONS:

    function Union (This_Set : in Set; That_Set : in Set) return Set;
    --
    -- Returns a new set which is the union of the two sets.

    function Intersection (This_Set : in Set; That_Set : in Set) return Set;
    --
    -- Returns a new set which is the intersection of the two sets.

    function Exclusive_Or (This_Set : in Set; That_Set : in Set) return Set;
    --
    -- Returns a new set which is the exclusive-or of the two sets.

    function Subtraction (This_Set : in Set; Except_For : in Set) return Set;
    --
    -- Returns a new set which contains all elements in the first set
    -- except for those which are also in the second set.

    function Subset (This_Set : in Set; Contains : in Set) return Boolean;
    --
    -- Returns True if the second set is a subset of the first set.

    function Proper_Subset
                (This_Set : in Set; Contains : in Set) return Boolean;
    --
    -- Returns True if the second set is a proper subset of the first set.


    -- CLOSURE OPERATIONS:

    -- The operations in this section create object sets based on the
    -- dependency relationships between Ada units. There are several
    -- parameters common to these operations:
    --
    -- * Specs_Only:
    --
    --      When this parameter is True, only Ada specs will be included.
    --
    -- * Transitive:
    --
    --      When this parameter is True, an object set will be generated
    --      using transitive closure (if 'A' depends on 'B', and 'B'
    --      depends on 'C', then 'A' depends on 'C' transitively).
    --
    -- * Include_Universe_Mirrors:
    --
    --      When this parameter is True, Ada specs which are an integral
    --      part of the Rational Environment will be included.
    --
    -- * Code_Share_Generics:
    --
    --      When this parameter is True, generic instantiations will be
    --      analyzed using a code-sharing model (as on the R1000).
    --
    --      When this parameter is False, generic instantiations will be
    --      analyzed using a macro in-line expansion model (as on a VAX).
    --
    -- * This_Activity:
    --
    --      This parameter allows the client to specify which activity should
    --      be used when subsystems are involved. In the default case, the
    --      activity is empty and dependencies will not cross view boundaries.

    function Dependencies_On (Unit : in Element;
                              Specs_Only : in Boolean := False;
                              Transitive : in Boolean := True;
                              Include_Universe_Mirrors : in Boolean := False;
                              Code_Share_Generics : in Boolean := True;
                              This_Activity : in Activity.Activity_Name :=
                                 Activity.The_Current_Activity) return Set;
    --
    -- Returns a set containing every element which depends on the specified
    -- unit. If the unit is a spec in a load view, the dependencies on the
    -- corresponding spec in the spec view will be added to the closure.

    function Dependencies_On (Units : in Set;
                              Specs_Only : in Boolean := False;
                              Transitive : in Boolean := True;
                              Include_Universe_Mirrors : in Boolean := False;
                              Code_Share_Generics : in Boolean := True;
                              This_Activity : in Activity.Activity_Name :=
                                 Activity.The_Current_Activity) return Set;

    function Dependencies_By (Unit : in Element;
                              Specs_Only : in Boolean := False;
                              Transitive : in Boolean := True;
                              Include_Universe_Mirrors : in Boolean := False;
                              Code_Share_Generics : in Boolean := True;
                              This_Activity : in Activity.Activity_Name :=
                                 Activity.The_Current_Activity) return Set;
    --
    -- Returns a set containing every element which is depended upon by the
    -- specified unit. If the element depends upon a spec in a spec view,
    -- the corresponding spec in the load view will be added to the closure.

    function Dependencies_By (Units : in Set;
                              Specs_Only : in Boolean := False;
                              Transitive : in Boolean := True;
                              Include_Universe_Mirrors : in Boolean := False;
                              Code_Share_Generics : in Boolean := True;
                              This_Activity : in Activity.Activity_Name :=
                                 Activity.The_Current_Activity) return Set;

    function Family (Unit : in Element;
                     This_Activity : in Activity.Activity_Name :=
                        Activity.The_Current_Activity) return Set;
    --
    -- Returns a set containing the elements in the "family" of the specified
    -- unit. A family is defined as follows:
    --
    --      For a subunit: the subunit itself, and the transitive
    --      closure of all subunits of the subunit.
    --
    --      For a body: the body itself, all subunits of the body,
    --      and the families of those subunits.
    --
    --      For an ordinary spec: the spec itself, the body associated
    --      with the spec, and the family of the body.
    --
    --      For a spec in a spec view: the family of the corresponding
    --      spec in the load view specified in the activity.

    function Execution_Closure_For
                (Unit : in Element;
                 Include_Universe_Mirrors : in Boolean := False;
                 This_Activity : in Activity.Activity_Name :=
                    Activity.The_Current_Activity) return Set;
    --
    -- Returns a set containing every element which must be coded in
    -- order to execute the specified unit.

end Object_Sets;