-- CA11017.A
--
--                             Grant of Unlimited Rights
--
--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained 
--     unlimited rights in the software and documentation contained herein.
--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making 
--     this public release, the Government intends to confer upon all 
--     recipients unlimited rights  equal to those held by the Government.  
--     These rights include rights to use, duplicate, release or disclose the 
--     released technical data and computer software in whole or in part, in 
--     any manner and for any purpose whatsoever, and to have or permit others 
--     to do so.
--
--                                    DISCLAIMER
--
--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED 
--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE 
--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--     PARTICULAR PURPOSE OF SAID MATERIAL.
--*
--
-- OBJECTIVE:
--      Check that body of the parent package may depend on one of its own 
--      public children.
--
-- TEST DESCRIPTION:
--      A scenario is created that demonstrates the potential of adding a
--      public child during code maintenance without distubing a large 
--      subsystem.  After child is added to the subsystem, a maintainer
--      decides to take advantage of the new functionality and rewrites
--      the parent's body.
--
--      Declare a string abstraction in a package which manipulates string
--      replacement. Define a parent package which provides operations for 
--      a record type with discriminant.  Declare a public child of this 
--      package which adds functionality to the original subsystem.  In the 
--      parent body, call operations from the public child.
--
--      In the main program, check that operations in the parent and public 
--      child perform as expected.
--
--
-- CHANGE HISTORY:
--      06 Dec 94   SAIC    ACVC 2.0
--
--!
-- Simulates application which manipulates strings.
package CA11017_0 is               
   type String_Rec (The_Size : positive) is private;
   type Substring is new string;
   -- ... Various other types used by the application.
   procedure Replace (In_The_String   : in out String_Rec;
                      At_The_Position : in     positive;
                      With_The_String : in     String_Rec);
   -- ... Various other operations used by the application.
private
   -- Different size for each individual record.
   type String_Rec (The_Size : positive) is
      record
         The_Length  : natural := 0;
         The_Content : Substring (1 .. The_Size);
      end record;
end CA11017_0;
     --=================================================================--
-- Public child added during code maintenance without disturbing a 
-- large system.  This public child would add functionality to the
-- original system.
package CA11017_0.CA11017_1 is    
   Position_Error : exception;
   function Equal_Length (Left  : in String_Rec;
                          Right : in String_Rec) return boolean;
   function Same_Content (Left  : in String_Rec;
                          Right : in String_Rec) return boolean;
   procedure Copy (From_The_Substring : in     Substring;
                   To_The_String      : in out String_Rec);
   -- ... Various other operations used by the application.
end CA11017_0.CA11017_1;
     --=================================================================--
package body CA11017_0.CA11017_1 is    
   function Equal_Length (Left  : in String_Rec;
                          Right : in String_Rec) return boolean is
   -- Quick comparison between the lengths of the input strings.
   begin
      return (Left.The_Length = Right.The_Length);  -- Parent's private
                                                    -- type.
   end Equal_Length;
   --------------------------------------------------------------------
   function Same_Content (Left  : in String_Rec;
                          Right : in String_Rec) return boolean is
   begin
      for I in 1 .. Left.The_Length loop
         if Left.The_Content (I) = Right.The_Content (I) then
            return true;
         else
            return false;
         end if;
      end loop;
   end Same_Content;
   --------------------------------------------------------------------
   procedure Copy (From_The_Substring : in     Substring;
                   To_The_String      : in out String_Rec) is
   begin
      To_The_String.The_Content        -- Parent's private type.
        (1 .. From_The_Substring'length) := From_The_Substring;
      To_The_String.The_Length         -- Parent's private type.
                                         := From_The_Substring'length;
   end Copy;
end CA11017_0.CA11017_1;
     --=================================================================--
--  After child is added to the subsystem, a maintainer decides
--  to take advantage of the new functionality and rewrites the
--  parent's body.
with CA11017_0.CA11017_1;
package body CA11017_0 is
   -- Calls functions from public child for a quick comparison of the
   -- input strings.  If their lengths are the same, do the replacement.
   procedure Replace (In_The_String   : in out String_Rec;
                      At_The_Position : in     positive;
                      With_The_String : in     String_Rec) is
      End_Position : natural := At_The_Position +
                                With_The_String.The_Length - 1;
   begin
      if not CA11017_0.CA11017_1.Equal_Length  -- Public child's operation.
        (With_The_String, In_The_String) then
           raise CA11017_0.CA11017_1.Position_Error;                 
                                               -- Public child's exception.
      else 
         In_The_String.The_Content (At_The_Position .. End_Position) :=
           With_The_String.The_Content (1 .. With_The_String.The_Length);
      end if;
   end Replace;
end CA11017_0;
     --=================================================================--
with Report;
with CA11017_0.CA11017_1;   -- Explicit with public child package,
                            -- implicit with parent package (CA11017_0).
procedure CA11017 is
   package String_Pkg renames CA11017_0;
   use String_Pkg;
begin
   Report.Test ("CA11017", "Check that body of the parent package can " &
                "depend on one of its own public children");
-- Both input strings have the same size. Replace the first string by the 
-- second string.  
        Replace_Subtest:
        declare
           The_First_String, The_Second_String : String_Rec (16);
                                                 -- Parent's private type.
           The_Position                        : positive := 1;
        begin
           CA11017_1.Copy ("This is the time", 
                           To_The_String => The_First_String); 
           CA11017_1.Copy ("For all good men", The_Second_String); 
           Replace (The_First_String, The_Position, The_Second_String);
  
           -- Compare results using function from public child since
           -- the type is private.
           if not CA11017_1.Same_Content
                            (The_First_String, The_Second_String) then
              Report.Failed ("Incorrect results");
           end if;
        end Replace_Subtest;
-- During processing, the application may erroneously attempt to replace
-- strings of different size. This would result in the raising of an 
-- exception.                                                       
        Exception_Subtest:
        declare
           The_First_String  : String_Rec (17);
                                                 -- Parent's private type.
           The_Second_String : String_Rec (13);
                                                 -- Parent's private type.
           The_Position      : positive := 2;
        begin
           CA11017_1.Copy (" ACVC Version 2.0", The_First_String); 
           CA11017_1.Copy (From_The_Substring => "ACVC 9X Basic", 
                           To_The_String      => The_Second_String); 
           Replace (The_First_String, The_Position, The_Second_String);
           Report.Failed ("Exception was not raised");
        exception
           when CA11017_1.Position_Error =>
                  Report.Comment ("Exception is raised as expected");
        end Exception_Subtest;
   Report.Result;
end CA11017;