-----------------------------------------------------------------------
--  AWA.Comments.Models -- AWA.Comments.Models
-----------------------------------------------------------------------
--  File generated by ada-gen DO NOT MODIFY
--  Template used: templates/model/package-spec.xhtml
--  Ada Generator: https://ada-gen.googlecode.com/svn/trunk Revision 1095
-----------------------------------------------------------------------
--  Copyright (C) 2013 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
pragma Warnings (Off, "unit * is not referenced");
with ADO.Sessions;
with ADO.Objects;
with ADO.Statements;
with ADO.SQL;
with ADO.Schemas;
with ADO.Queries;
with ADO.Queries.Loaders;
with Ada.Calendar;
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
with Util.Beans.Objects;
with Util.Beans.Objects.Enums;
with Util.Beans.Basic.Lists;
with AWA.Users.Models;
with Util.Beans.Methods;
pragma Warnings (On, "unit * is not referenced");
package AWA.Comments.Models is
   --  --------------------
   --  The status type defines whether the comment is visible or not.
   --  The comment can be put in the COMMENT_WAITING state so that
   --  it is not immediately visible. It must be put in the COMMENT_PUBLISHED
   --  state to be visible.
   --  --------------------
   type Status_Type is (COMMENT_PUBLISHED, COMMENT_WAITING, COMMENT_SPAM, COMMENT_BLOCKED, COMMENT_ARCHIVED);
   for Status_Type use (COMMENT_PUBLISHED => 0, COMMENT_WAITING => 1, COMMENT_SPAM => 2, COMMENT_BLOCKED => 3, COMMENT_ARCHIVED => 4);
   package Status_Type_Objects is
      new Util.Beans.Objects.Enums (Status_Type);

   type Comment_Ref is new ADO.Objects.Object_Ref with null record;

   --  --------------------
   --  The Comment table records a user comment associated with a database entity.
   --  The comment can be associated with any other database record.
   --  --------------------
   --  Create an object key for Comment.
   function Comment_Key (Id : in ADO.Identifier) return ADO.Objects.Object_Key;
   --  Create an object key for Comment from a string.
   --  Raises Constraint_Error if the string cannot be converted into the object key.
   function Comment_Key (Id : in String) return ADO.Objects.Object_Key;

   Null_Comment : constant Comment_Ref;
   function "=" (Left, Right : Comment_Ref'Class) return Boolean;

   --  Set the comment publication date
   procedure Set_Create_Date (Object : in out Comment_Ref;
                              Value  : in Ada.Calendar.Time);

   --  Get the comment publication date
   function Get_Create_Date (Object : in Comment_Ref)
                 return Ada.Calendar.Time;

   --  Set the comment message.
   procedure Set_Message (Object : in out Comment_Ref;
                          Value  : in Ada.Strings.Unbounded.Unbounded_String);
   procedure Set_Message (Object : in out Comment_Ref;
                          Value : in String);

   --  Get the comment message.
   function Get_Message (Object : in Comment_Ref)
                 return Ada.Strings.Unbounded.Unbounded_String;
   function Get_Message (Object : in Comment_Ref)
                 return String;

   --  Set the entity identifier to which this comment is associated
   procedure Set_Entity_Id (Object : in out Comment_Ref;
                            Value  : in ADO.Identifier);

   --  Get the entity identifier to which this comment is associated
   function Get_Entity_Id (Object : in Comment_Ref)
                 return ADO.Identifier;

   --  Set the comment identifier
   procedure Set_Id (Object : in out Comment_Ref;
                     Value  : in ADO.Identifier);

   --  Get the comment identifier
   function Get_Id (Object : in Comment_Ref)
                 return ADO.Identifier;
   --  Get the optimistic lock version.
   function Get_Version (Object : in Comment_Ref)
                 return Integer;

   --  Set the entity type that identifies the table to which the comment is associated.
   procedure Set_Entity_Type (Object : in out Comment_Ref;
                              Value  : in ADO.Entity_Type);

   --  Get the entity type that identifies the table to which the comment is associated.
   function Get_Entity_Type (Object : in Comment_Ref)
                 return ADO.Entity_Type;

   --  Set the comment status to decide whether the comment is visible (published) or not.
   procedure Set_Status (Object : in out Comment_Ref;
                         Value  : in Status_Type);

   --  Get the comment status to decide whether the comment is visible (published) or not.
   function Get_Status (Object : in Comment_Ref)
                 return Status_Type;

   --
   procedure Set_Author (Object : in out Comment_Ref;
                         Value  : in AWA.Users.Models.User_Ref'Class);

   --
   function Get_Author (Object : in Comment_Ref)
                 return AWA.Users.Models.User_Ref'Class;

   --  Load the entity identified by 'Id'.
   --  Raises the NOT_FOUND exception if it does not exist.
   procedure Load (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in ADO.Identifier);

   --  Load the entity identified by 'Id'.
   --  Returns True in Found if the object was found and False if it does not exist.
   procedure Load (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in ADO.Identifier;
                   Found   : out Boolean);

   --  Find and load the entity.
   overriding
   procedure Find (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean);

   --  Save the entity.  If the entity does not have an identifier, an identifier is allocated
   --  and it is inserted in the table.  Otherwise, only data fields which have been changed
   --  are updated.
   overriding
   procedure Save (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Master_Session'Class);

   --  Delete the entity.
   overriding
   procedure Delete (Object  : in out Comment_Ref;
                     Session : in out ADO.Sessions.Master_Session'Class);

   overriding
   function Get_Value (From : in Comment_Ref;
                       Name : in String) return Util.Beans.Objects.Object;

   --  Table definition
   COMMENT_TABLE : constant ADO.Schemas.Class_Mapping_Access;

   --  Internal method to allocate the Object_Record instance
   overriding
   procedure Allocate (Object : in out Comment_Ref);

   --  Copy of the object.
   procedure Copy (Object : in Comment_Ref;
                   Into   : in out Comment_Ref);

   --  --------------------
   --  The comment information.
   --  --------------------
   type Comment_Info is new Util.Beans.Basic.Readonly_Bean with record
      --  the comment identifier.
      Id : ADO.Identifier;

      --  the comment author's name.
      Author : Ada.Strings.Unbounded.Unbounded_String;

      --  the comment author's email.
      Email : Ada.Strings.Unbounded.Unbounded_String;

      --  the comment date.
      Date : Ada.Calendar.Time;

      --  the comment text.
      Comment : Ada.Strings.Unbounded.Unbounded_String;

   end record;

   --  Get the bean attribute identified by the given name.
   overriding
   function Get_Value (From : in Comment_Info;
                       Name : in String) return Util.Beans.Objects.Object;

   package Comment_Info_Beans is
      new Util.Beans.Basic.Lists (Element_Type => Comment_Info);
   package Comment_Info_Vectors renames Comment_Info_Beans.Vectors;
   subtype Comment_Info_List_Bean is Comment_Info_Beans.List_Bean;

   type Comment_Info_List_Bean_Access is access all Comment_Info_List_Bean;

   --  Run the query controlled by Context and append the list in Object.
   procedure List (Object  : in out Comment_Info_List_Bean'Class;
                   Session : in out ADO.Sessions.Session'Class;
                   Context : in out ADO.Queries.Context'Class);

   subtype Comment_Info_Vector is Comment_Info_Vectors.Vector;

   --  Run the query controlled by Context and append the list in Object.
   procedure List (Object  : in out Comment_Info_Vector;
                   Session : in out ADO.Sessions.Session'Class;
                   Context : in out ADO.Queries.Context'Class);

   Query_Comment_List : constant ADO.Queries.Query_Definition_Access;

   type Comment_Bean is abstract new AWA.Comments.Models.Comment_Ref
     and Util.Beans.Basic.Bean and Util.Beans.Methods.Method_Bean with null record;

   --  This bean provides some methods that can be used in a Method_Expression.
   overriding
   function Get_Method_Bindings (From : in Comment_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access;

   --  Set the value identified by the name.
   overriding
   procedure Set_Value (Item  : in out Comment_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object);

   procedure Create (Bean : in out Comment_Bean;
                    Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

   procedure Delete (Bean : in out Comment_Bean;
                    Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

   procedure Save (Bean : in out Comment_Bean;
                  Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

private
   COMMENT_NAME : aliased constant String := "awa_comments";
   COL_0_1_NAME : aliased constant String := "create_date";
   COL_1_1_NAME : aliased constant String := "message";
   COL_2_1_NAME : aliased constant String := "entity_id";
   COL_3_1_NAME : aliased constant String := "id";
   COL_4_1_NAME : aliased constant String := "version";
   COL_5_1_NAME : aliased constant String := "entity_type";
   COL_6_1_NAME : aliased constant String := "status";
   COL_7_1_NAME : aliased constant String := "author_id";

   COMMENT_DEF : aliased constant ADO.Schemas.Class_Mapping :=
     (Count => 8,
      Table => COMMENT_NAME'Access,
      Members => (
         1 => COL_0_1_NAME'Access,
         2 => COL_1_1_NAME'Access,
         3 => COL_2_1_NAME'Access,
         4 => COL_3_1_NAME'Access,
         5 => COL_4_1_NAME'Access,
         6 => COL_5_1_NAME'Access,
         7 => COL_6_1_NAME'Access,
         8 => COL_7_1_NAME'Access
)
     );
   COMMENT_TABLE : constant ADO.Schemas.Class_Mapping_Access
      := COMMENT_DEF'Access;

   Null_Comment : constant Comment_Ref
      := Comment_Ref'(ADO.Objects.Object_Ref with others => <>);

   type Comment_Impl is
      new ADO.Objects.Object_Record (Key_Type => ADO.Objects.KEY_INTEGER,
                                     Of_Class => COMMENT_DEF'Access)
   with record
       Create_Date : Ada.Calendar.Time;
       Message : Ada.Strings.Unbounded.Unbounded_String;
       Entity_Id : ADO.Identifier;
       Version : Integer;
       Entity_Type : ADO.Entity_Type;
       Status : Status_Type;
       Author : AWA.Users.Models.User_Ref;
   end record;

   type Comment_Access is access all Comment_Impl;

   overriding
   procedure Destroy (Object : access Comment_Impl);

   overriding
   procedure Find (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean);

   overriding
   procedure Load (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Session'Class);
   procedure Load (Object  : in out Comment_Impl;
                   Stmt    : in out ADO.Statements.Query_Statement'Class;
                   Session : in out ADO.Sessions.Session'Class);

   overriding
   procedure Save (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Master_Session'Class);

   procedure Create (Object  : in out Comment_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class);

   overriding
   procedure Delete (Object  : in out Comment_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class);

   procedure Set_Field (Object : in out Comment_Ref'Class;
                        Impl   : out Comment_Access);

   package File_1 is
      new ADO.Queries.Loaders.File (Path => "comment-queries.xml",
                                    Sha1 => "23485D2C3F50D233CB8D52A2414B417F4296B51A");

   package Def_Commentinfo_Comment_List is
      new ADO.Queries.Loaders.Query (Name => "comment-list",
                                     File => File_1.File'Access);
   Query_Comment_List : constant ADO.Queries.Query_Definition_Access
   := Def_Commentinfo_Comment_List.Query'Access;
end AWA.Comments.Models;

-----------------------------------------------------------------------
--  AWA.Comments.Models -- AWA.Comments.Models
-----------------------------------------------------------------------
--  File generated by ada-gen DO NOT MODIFY
--  Template used: templates/model/package-spec.xhtml
--  Ada Generator: https://ada-gen.googlecode.com/svn/trunk Revision 1095
-----------------------------------------------------------------------
--  Copyright (C) 2013 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
pragma Warnings (Off, "unit * is not referenced");
with ADO.Sessions;
with ADO.Objects;
with ADO.Statements;
with ADO.SQL;
with ADO.Schemas;
with ADO.Queries;
with ADO.Queries.Loaders;
with Ada.Calendar;
with Ada.Containers.Vectors;
with Ada.Strings.Unbounded;
with Util.Beans.Objects;
with Util.Beans.Objects.Enums;
with Util.Beans.Basic.Lists;
with AWA.Users.Models;
with Util.Beans.Methods;
pragma Warnings (On, "unit * is not referenced");
package AWA.Comments.Models is
   --  --------------------
   --  The status type defines whether the comment is visible or not.
   --  The comment can be put in the COMMENT_WAITING state so that
   --  it is not immediately visible. It must be put in the COMMENT_PUBLISHED
   --  state to be visible.
   --  --------------------
   type Status_Type is (COMMENT_PUBLISHED, COMMENT_WAITING, COMMENT_SPAM, COMMENT_BLOCKED, COMMENT_ARCHIVED);
   for Status_Type use (COMMENT_PUBLISHED => 0, COMMENT_WAITING => 1, COMMENT_SPAM => 2, COMMENT_BLOCKED => 3, COMMENT_ARCHIVED => 4);
   package Status_Type_Objects is
      new Util.Beans.Objects.Enums (Status_Type);

   type Comment_Ref is new ADO.Objects.Object_Ref with null record;

   --  --------------------
   --  The Comment table records a user comment associated with a database entity.
   --  The comment can be associated with any other database record.
   --  --------------------
   --  Create an object key for Comment.
   function Comment_Key (Id : in ADO.Identifier) return ADO.Objects.Object_Key;
   --  Create an object key for Comment from a string.
   --  Raises Constraint_Error if the string cannot be converted into the object key.
   function Comment_Key (Id : in String) return ADO.Objects.Object_Key;

   Null_Comment : constant Comment_Ref;
   function "=" (Left, Right : Comment_Ref'Class) return Boolean;

   --  Set the comment publication date
   procedure Set_Create_Date (Object : in out Comment_Ref;
                              Value  : in Ada.Calendar.Time);

   --  Get the comment publication date
   function Get_Create_Date (Object : in Comment_Ref)
                 return Ada.Calendar.Time;

   --  Set the comment message.
   procedure Set_Message (Object : in out Comment_Ref;
                          Value  : in Ada.Strings.Unbounded.Unbounded_String);
   procedure Set_Message (Object : in out Comment_Ref;
                          Value : in String);

   --  Get the comment message.
   function Get_Message (Object : in Comment_Ref)
                 return Ada.Strings.Unbounded.Unbounded_String;
   function Get_Message (Object : in Comment_Ref)
                 return String;

   --  Set the entity identifier to which this comment is associated
   procedure Set_Entity_Id (Object : in out Comment_Ref;
                            Value  : in ADO.Identifier);

   --  Get the entity identifier to which this comment is associated
   function Get_Entity_Id (Object : in Comment_Ref)
                 return ADO.Identifier;

   --  Set the comment identifier
   procedure Set_Id (Object : in out Comment_Ref;
                     Value  : in ADO.Identifier);

   --  Get the comment identifier
   function Get_Id (Object : in Comment_Ref)
                 return ADO.Identifier;
   --  Get the optimistic lock version.
   function Get_Version (Object : in Comment_Ref)
                 return Integer;

   --  Set the entity type that identifies the table to which the comment is associated.
   procedure Set_Entity_Type (Object : in out Comment_Ref;
                              Value  : in ADO.Entity_Type);

   --  Get the entity type that identifies the table to which the comment is associated.
   function Get_Entity_Type (Object : in Comment_Ref)
                 return ADO.Entity_Type;

   --  Set the comment status to decide whether the comment is visible (published) or not.
   procedure Set_Status (Object : in out Comment_Ref;
                         Value  : in Status_Type);

   --  Get the comment status to decide whether the comment is visible (published) or not.
   function Get_Status (Object : in Comment_Ref)
                 return Status_Type;

   --
   procedure Set_Author (Object : in out Comment_Ref;
                         Value  : in AWA.Users.Models.User_Ref'Class);

   --
   function Get_Author (Object : in Comment_Ref)
                 return AWA.Users.Models.User_Ref'Class;

   --  Load the entity identified by 'Id'.
   --  Raises the NOT_FOUND exception if it does not exist.
   procedure Load (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in ADO.Identifier);

   --  Load the entity identified by 'Id'.
   --  Returns True in Found if the object was found and False if it does not exist.
   procedure Load (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Id      : in ADO.Identifier;
                   Found   : out Boolean);

   --  Find and load the entity.
   overriding
   procedure Find (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean);

   --  Save the entity.  If the entity does not have an identifier, an identifier is allocated
   --  and it is inserted in the table.  Otherwise, only data fields which have been changed
   --  are updated.
   overriding
   procedure Save (Object  : in out Comment_Ref;
                   Session : in out ADO.Sessions.Master_Session'Class);

   --  Delete the entity.
   overriding
   procedure Delete (Object  : in out Comment_Ref;
                     Session : in out ADO.Sessions.Master_Session'Class);

   overriding
   function Get_Value (From : in Comment_Ref;
                       Name : in String) return Util.Beans.Objects.Object;

   --  Table definition
   COMMENT_TABLE : constant ADO.Schemas.Class_Mapping_Access;

   --  Internal method to allocate the Object_Record instance
   overriding
   procedure Allocate (Object : in out Comment_Ref);

   --  Copy of the object.
   procedure Copy (Object : in Comment_Ref;
                   Into   : in out Comment_Ref);

   --  --------------------
   --  The comment information.
   --  --------------------
   type Comment_Info is new Util.Beans.Basic.Readonly_Bean with record
      --  the comment identifier.
      Id : ADO.Identifier;

      --  the comment author's name.
      Author : Ada.Strings.Unbounded.Unbounded_String;

      --  the comment author's email.
      Email : Ada.Strings.Unbounded.Unbounded_String;

      --  the comment date.
      Date : Ada.Calendar.Time;

      --  the comment text.
      Comment : Ada.Strings.Unbounded.Unbounded_String;

   end record;

   --  Get the bean attribute identified by the given name.
   overriding
   function Get_Value (From : in Comment_Info;
                       Name : in String) return Util.Beans.Objects.Object;

   package Comment_Info_Beans is
      new Util.Beans.Basic.Lists (Element_Type => Comment_Info);
   package Comment_Info_Vectors renames Comment_Info_Beans.Vectors;
   subtype Comment_Info_List_Bean is Comment_Info_Beans.List_Bean;

   type Comment_Info_List_Bean_Access is access all Comment_Info_List_Bean;

   --  Run the query controlled by Context and append the list in Object.
   procedure List (Object  : in out Comment_Info_List_Bean'Class;
                   Session : in out ADO.Sessions.Session'Class;
                   Context : in out ADO.Queries.Context'Class);

   subtype Comment_Info_Vector is Comment_Info_Vectors.Vector;

   --  Run the query controlled by Context and append the list in Object.
   procedure List (Object  : in out Comment_Info_Vector;
                   Session : in out ADO.Sessions.Session'Class;
                   Context : in out ADO.Queries.Context'Class);

   Query_Comment_List : constant ADO.Queries.Query_Definition_Access;

   type Comment_Bean is abstract new AWA.Comments.Models.Comment_Ref
     and Util.Beans.Basic.Bean and Util.Beans.Methods.Method_Bean with null record;

   --  This bean provides some methods that can be used in a Method_Expression.
   overriding
   function Get_Method_Bindings (From : in Comment_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access;

   --  Set the value identified by the name.
   overriding
   procedure Set_Value (Item  : in out Comment_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object);

   procedure Create (Bean : in out Comment_Bean;
                    Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

   procedure Delete (Bean : in out Comment_Bean;
                    Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

   procedure Save (Bean : in out Comment_Bean;
                  Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is abstract;

private
   COMMENT_NAME : aliased constant String := "awa_comment";
   COL_0_1_NAME : aliased constant String := "create_date";
   COL_1_1_NAME : aliased constant String := "message";
   COL_2_1_NAME : aliased constant String := "entity_id";
   COL_3_1_NAME : aliased constant String := "id";
   COL_4_1_NAME : aliased constant String := "version";
   COL_5_1_NAME : aliased constant String := "entity_type";
   COL_6_1_NAME : aliased constant String := "status";
   COL_7_1_NAME : aliased constant String := "author_id";

   COMMENT_DEF : aliased constant ADO.Schemas.Class_Mapping :=
     (Count => 8,
      Table => COMMENT_NAME'Access,
      Members => (
         1 => COL_0_1_NAME'Access,
         2 => COL_1_1_NAME'Access,
         3 => COL_2_1_NAME'Access,
         4 => COL_3_1_NAME'Access,
         5 => COL_4_1_NAME'Access,
         6 => COL_5_1_NAME'Access,
         7 => COL_6_1_NAME'Access,
         8 => COL_7_1_NAME'Access
)
     );
   COMMENT_TABLE : constant ADO.Schemas.Class_Mapping_Access
      := COMMENT_DEF'Access;

   Null_Comment : constant Comment_Ref
      := Comment_Ref'(ADO.Objects.Object_Ref with others => <>);

   type Comment_Impl is
      new ADO.Objects.Object_Record (Key_Type => ADO.Objects.KEY_INTEGER,
                                     Of_Class => COMMENT_DEF'Access)
   with record
       Create_Date : Ada.Calendar.Time;
       Message : Ada.Strings.Unbounded.Unbounded_String;
       Entity_Id : ADO.Identifier;
       Version : Integer;
       Entity_Type : ADO.Entity_Type;
       Status : Status_Type;
       Author : AWA.Users.Models.User_Ref;
   end record;

   type Comment_Access is access all Comment_Impl;

   overriding
   procedure Destroy (Object : access Comment_Impl);

   overriding
   procedure Find (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Session'Class;
                   Query   : in ADO.SQL.Query'Class;
                   Found   : out Boolean);

   overriding
   procedure Load (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Session'Class);
   procedure Load (Object  : in out Comment_Impl;
                   Stmt    : in out ADO.Statements.Query_Statement'Class;
                   Session : in out ADO.Sessions.Session'Class);

   overriding
   procedure Save (Object  : in out Comment_Impl;
                   Session : in out ADO.Sessions.Master_Session'Class);

   procedure Create (Object  : in out Comment_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class);

   overriding
   procedure Delete (Object  : in out Comment_Impl;
                     Session : in out ADO.Sessions.Master_Session'Class);

   procedure Set_Field (Object : in out Comment_Ref'Class;
                        Impl   : out Comment_Access);

   package File_1 is
      new ADO.Queries.Loaders.File (Path => "comment-queries.xml",
                                    Sha1 => "23485D2C3F50D233CB8D52A2414B417F4296B51A");

   package Def_Commentinfo_Comment_List is
      new ADO.Queries.Loaders.Query (Name => "comment-list",
                                     File => File_1.File'Access);
   Query_Comment_List : constant ADO.Queries.Query_Definition_Access
   := Def_Commentinfo_Comment_List.Query'Access;
end AWA.Comments.Models;

Rebuild the model files (rename table awa_comment)


-----------------------------------------------------------------------
--  asf.beans -- Bean Registration and Factory
--  Copyright (C) 2009, 2010, 2011 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Strings.Hash;
with Ada.Strings.Unbounded;

with Util.Beans.Basic;
with Util.Refs;

with EL.Beans;
with EL.Contexts;

with Ada.Containers.Hashed_Maps;
with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Strings.Unbounded.Hash;

--  The ASF.Beans package is a registry for creating request, session
--  and application beans.
--
--  First, an application or a module registers in a class factory the class
--  of objects that can be created.  Each class is represented by a Class_Binding
--  interface that allows to create instances of the given class.  Each class
--  is associated with a unique name in the class factory (ie, the class name).
--  This step is done when the application or module is initialized.
--
--  Second, a set of application configuration files define the runtime bean objects
--  that can be created automatically when a request is processed.  Each runtime bean
--  object is associated with a bean name, a bean type identifying the class of object,
--  and a scope that identifies the lifespan of the object.
--
--  When a request is processed and a bean must be created, the bean factory is
--  searched to find a the object class and object scope (a Bean_Binding).
--  The Class_Binding associated with the Bean_Binding is then used
--  to create the object.
package ASF.Beans is

   --  Defines the scope of the bean instance.
   type Scope_Type is
     (
      --  Application scope means the bean is shared by all sessions and requests
      APPLICATION_SCOPE,

      --  Session scope means the bean is created one for each session.
      SESSION_SCOPE,

      --  Request scope means the bean is created for each request
      REQUEST_SCOPE,

      ANY_SCOPE);

   --  ------------------------------
   --  Class Binding
   --  ------------------------------
   --  The Class_Binding provides an operation to create objects of a given class.
   type Class_Binding is abstract new Util.Refs.Ref_Entity with null record;
   type Class_Binding_Access is access all Class_Binding'Class;

   procedure Create (Factory : in Class_Binding;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access) is abstract;

   --  Simplified bean creation.  A Create_Bean_Access function can be registered
   --  as a simplified class binding to create bean instances.
   type Create_Bean_Access is access function return Util.Beans.Basic.Readonly_Bean_Access;

   --  ------------------------------
   --  Bean initialization
   --  ------------------------------
   --  After a bean object is created, it can be initialized with a set of values defined
   --  by the EL.Beans.Param_Value type which holds the bean property name as well
   --  as an EL expression that will be evaluated to get the property value.
   type Parameter_Bean is new Util.Refs.Ref_Entity with record
      Params : EL.Beans.Param_Vectors.Vector;
   end record;
   type Parameter_Bean_Access is access all Parameter_Bean;

   package Parameter_Bean_Ref is
     new Util.Refs.Indefinite_References (Element_Type   => Parameter_Bean,
                                          Element_Access => Parameter_Bean_Access);

   --  ------------------------------
   --  Bean Factory
   --  ------------------------------
   --  The registry maintains a list of creation bindings which allow to create
   --  a bean object of a particular type.
   type Bean_Factory is limited private;

   --  Register under the name identified by Name the class instance Class.
   procedure Register_Class (Factory : in out Bean_Factory;
                             Name    : in String;
                             Class   : in Class_Binding_Access);

   --  Register under the name identified by Name a function to create a bean.
   --  This is a simplified class registration.
   procedure Register_Class (Factory : in out Bean_Factory;
                             Name    : in String;
                             Handler : in Create_Bean_Access);

   --  Register all the definitions from a factory to a main factory.
   procedure Register (Factory : in out Bean_Factory;
                       From    : in Bean_Factory);

   --  Register the bean identified by Name and associated with the class Class.
   --  The class must have been registered by using the Register class operation.
   --  The scope defines the scope of the bean.
   procedure Register (Factory : in out Bean_Factory;
                       Name    : in String;
                       Class   : in String;
                       Params  : in Parameter_Bean_Ref.Ref;
                       Scope   : in Scope_Type := REQUEST_SCOPE);

   --  Register the bean identified by Name and associated with the class Class.
   --  The class must have been registered by using the Register class operation.
   --  The scope defines the scope of the bean.
   procedure Register (Factory : in out Bean_Factory;
                       Name    : in String;
                       Class   : in Class_Binding_Access;
                       Params  : in Parameter_Bean_Ref.Ref;
                       Scope   : in Scope_Type := REQUEST_SCOPE);

   --  Create a bean by using the create operation registered for the name
   procedure Create (Factory : in Bean_Factory;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Context : in EL.Contexts.ELContext'Class;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access;
                     Scope   : out Scope_Type);

private

   use Ada.Strings.Unbounded;

   package Class_Binding_Ref is
     new Util.Refs.Indefinite_References (Element_Type   => Class_Binding'Class,
                                          Element_Access => Class_Binding_Access);

   package Registry_Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type     => String,
                                                Element_Type => Class_Binding_Ref.Ref,
                                                Hash         => Ada.Strings.Hash,
                                                Equivalent_Keys => "=",
                                                "=" => Class_Binding_Ref."=");
   --  ------------------------------
   --  Default class binding record
   --  ------------------------------
   type Default_Class_Binding is new Class_Binding with record
      Create : Create_Bean_Access;
   end record;
   type Default_Class_Binding_Access is access all Default_Class_Binding'Class;

   --  Create a bean by using the registered create function.
   procedure Create (Factory : in Default_Class_Binding;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access);

   type Bean_Binding is record
      Scope  : Scope_Type;
      Create : Class_Binding_Ref.Ref;
      Params : Parameter_Bean_Ref.Ref;
   end record;

   package Bean_Maps is new
     Ada.Containers.Hashed_Maps (Key_Type     => Unbounded_String,
                                 Element_Type => Bean_Binding,
                                 Hash         => Ada.Strings.Unbounded.Hash,
                                 Equivalent_Keys => "=");

   type Bean_Factory is limited record
      Registry : Registry_Maps.Map;
      Map      : Bean_Maps.Map;
   end record;

end ASF.Beans;

-----------------------------------------------------------------------
--  asf.beans -- Bean Registration and Factory
--  Copyright (C) 2009, 2010, 2011, 2015 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Ada.Strings.Hash;
with Ada.Strings.Unbounded;

with Util.Beans.Basic;
with Util.Refs;

with EL.Beans;
with EL.Contexts;

with Ada.Containers.Hashed_Maps;
with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Strings.Unbounded.Hash;

--  The ASF.Beans package is a registry for creating request, session
--  and application beans.
--
--  First, an application or a module registers in a class factory the class
--  of objects that can be created.  Each class is represented by a Class_Binding
--  interface that allows to create instances of the given class.  Each class
--  is associated with a unique name in the class factory (ie, the class name).
--  This step is done when the application or module is initialized.
--
--  Second, a set of application configuration files define the runtime bean objects
--  that can be created automatically when a request is processed.  Each runtime bean
--  object is associated with a bean name, a bean type identifying the class of object,
--  and a scope that identifies the lifespan of the object.
--
--  When a request is processed and a bean must be created, the bean factory is
--  searched to find a the object class and object scope (a Bean_Binding).
--  The Class_Binding associated with the Bean_Binding is then used
--  to create the object.
package ASF.Beans is

   --  Defines the scope of the bean instance.
   type Scope_Type is
     (
      --  Application scope means the bean is shared by all sessions and requests
      APPLICATION_SCOPE,

      --  Session scope means the bean is created one for each session.
      SESSION_SCOPE,

      --  Request scope means the bean is created for each request
      REQUEST_SCOPE,

      ANY_SCOPE);

   --  ------------------------------
   --  Class Binding
   --  ------------------------------
   --  The Class_Binding provides an operation to create objects of a given class.
   type Class_Binding is abstract new Util.Refs.Ref_Entity with null record;
   type Class_Binding_Access is access all Class_Binding'Class;

   procedure Create (Factory : in Class_Binding;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access) is abstract;

   --  Simplified bean creation.  A Create_Bean_Access function can be registered
   --  as a simplified class binding to create bean instances.
   type Create_Bean_Access is access function return Util.Beans.Basic.Readonly_Bean_Access;

   --  ------------------------------
   --  Bean initialization
   --  ------------------------------
   --  After a bean object is created, it can be initialized with a set of values defined
   --  by the EL.Beans.Param_Value type which holds the bean property name as well
   --  as an EL expression that will be evaluated to get the property value.
   type Parameter_Bean is new Util.Refs.Ref_Entity with record
      Params : EL.Beans.Param_Vectors.Vector;
   end record;
   type Parameter_Bean_Access is access all Parameter_Bean;

   package Parameter_Bean_Ref is
     new Util.Refs.Indefinite_References (Element_Type   => Parameter_Bean,
                                          Element_Access => Parameter_Bean_Access);

   --  ------------------------------
   --  Bean Factory
   --  ------------------------------
   --  The registry maintains a list of creation bindings which allow to create
   --  a bean object of a particular type.
   type Bean_Factory is limited private;

   --  Register under the name identified by Name the class instance Class.
   procedure Register_Class (Factory : in out Bean_Factory;
                             Name    : in String;
                             Class   : in Class_Binding_Access);

   --  Register under the name identified by Name a function to create a bean.
   --  This is a simplified class registration.
   procedure Register_Class (Factory : in out Bean_Factory;
                             Name    : in String;
                             Handler : in Create_Bean_Access);

   --  Register all the definitions from a factory to a main factory.
   procedure Register (Factory : in out Bean_Factory;
                       From    : in Bean_Factory);

   --  Register the bean identified by Name and associated with the class Class.
   --  The class must have been registered by using the Register class operation.
   --  The scope defines the scope of the bean.
   procedure Register (Factory : in out Bean_Factory;
                       Name    : in String;
                       Class   : in String;
                       Params  : in Parameter_Bean_Ref.Ref;
                       Scope   : in Scope_Type := REQUEST_SCOPE);

   --  Register the bean identified by Name and associated with the class Class.
   --  The class must have been registered by using the Register class operation.
   --  The scope defines the scope of the bean.
   procedure Register (Factory : in out Bean_Factory;
                       Name    : in String;
                       Class   : in Class_Binding_Access;
                       Params  : in Parameter_Bean_Ref.Ref;
                       Scope   : in Scope_Type := REQUEST_SCOPE);

   --  Create a bean by using the create operation registered for the name
   procedure Create (Factory : in Bean_Factory;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Context : in EL.Contexts.ELContext'Class;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access;
                     Scope   : out Scope_Type);

   --  Create a map bean object that allows to associate name/value pairs in a bean.
   function Create_Map_Bean return Util.Beans.Basic.Readonly_Bean_Access;

private

   use Ada.Strings.Unbounded;

   package Class_Binding_Ref is
     new Util.Refs.Indefinite_References (Element_Type   => Class_Binding'Class,
                                          Element_Access => Class_Binding_Access);

   package Registry_Maps is
     new Ada.Containers.Indefinite_Hashed_Maps (Key_Type     => String,
                                                Element_Type => Class_Binding_Ref.Ref,
                                                Hash         => Ada.Strings.Hash,
                                                Equivalent_Keys => "=",
                                                "=" => Class_Binding_Ref."=");
   --  ------------------------------
   --  Default class binding record
   --  ------------------------------
   type Default_Class_Binding is new Class_Binding with record
      Create : Create_Bean_Access;
   end record;
   type Default_Class_Binding_Access is access all Default_Class_Binding'Class;

   --  Create a bean by using the registered create function.
   procedure Create (Factory : in Default_Class_Binding;
                     Name    : in Ada.Strings.Unbounded.Unbounded_String;
                     Result  : out Util.Beans.Basic.Readonly_Bean_Access);

   type Bean_Binding is record
      Scope  : Scope_Type;
      Create : Class_Binding_Ref.Ref;
      Params : Parameter_Bean_Ref.Ref;
   end record;

   package Bean_Maps is new
     Ada.Containers.Hashed_Maps (Key_Type     => Unbounded_String,
                                 Element_Type => Bean_Binding,
                                 Hash         => Ada.Strings.Unbounded.Hash,
                                 Equivalent_Keys => "=");

   type Bean_Factory is limited record
      Registry : Registry_Maps.Map;
      Map      : Bean_Maps.Map;
   end record;

end ASF.Beans;

Declare Create_Map_Bean function

Declare Create_Map_Bean function


-----------------------------------------------------------------------
--  awa-wikis-tests -- Unit tests for wikis module
--  Copyright (C) 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Util.Tests;
with AWA.Tests;
with Ada.Strings.Unbounded;

package AWA.Wikis.Tests is

   procedure Add_Tests (Suite : in Util.Tests.Access_Test_Suite);

   type Test is new AWA.Tests.Test with record
      Wiki_Ident : Ada.Strings.Unbounded.Unbounded_String;
      Page_Ident : Ada.Strings.Unbounded.Unbounded_String;
   end record;

   --  Get some access on the wiki page as anonymous users.
   procedure Verify_Anonymous (T     : in out Test;
                               Page  : in String;
                               Title : in String);

   --  Verify that the wiki lists contain the given page.
   procedure Verify_List_Contains (T    : in out Test;
                                   Page : in String);

   --  Test access to the wiki as anonymous user.
   procedure Test_Anonymous_Access (T : in out Test);

   --  Test creation of wiki space and page by simulating web requests.
   procedure Test_Create_Wiki (T : in out Test);

end AWA.Wikis.Tests;

-----------------------------------------------------------------------
--  awa-wikis-tests -- Unit tests for wikis module
--  Copyright (C) 2018 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------

with Util.Tests;
with AWA.Tests;
with Ada.Strings.Unbounded;

package AWA.Wikis.Tests is

   procedure Add_Tests (Suite : in Util.Tests.Access_Test_Suite);

   type Test is new AWA.Tests.Test with record
      Wiki_Ident : Ada.Strings.Unbounded.Unbounded_String;
      Page_Ident : Ada.Strings.Unbounded.Unbounded_String;
   end record;

   --  Get some access on the wiki page as anonymous users.
   procedure Verify_Anonymous (T     : in out Test;
                               Page  : in String;
                               Title : in String);

   --  Verify that the wiki lists contain the given page.
   procedure Verify_List_Contains (T    : in out Test;
                                   Page : in String);

   --  Test access to the wiki as anonymous user.
   procedure Test_Anonymous_Access (T : in out Test);

   --  Test creation of wiki space and page by simulating web requests.
   procedure Test_Create_Wiki (T : in out Test);

   --  Test getting a wiki page which does not exist.
   procedure Test_Missing_Page (T : in out Test);

end AWA.Wikis.Tests;

Declare Test_Missing_Page procedure

Declare Test_Missing_Page procedure


-----------------------------------------------------------------------
--  Memory Events - Definition and Analysis of memory events
--  Copyright (C) 2014 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Util.Log.Loggers;

with MAT.Memory.Readers;
package body MAT.Memory.Targets is

   --  The logger
   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("MAT.Memory.Targets");

   --  ------------------------------
   --  Initialize the target memory object to manage the memory slots, the stack frames
   --  and setup the reader to analyze the memory events.
   --  ------------------------------
   procedure Initialize (Memory : in out Target_Memory;
                         Reader : in out MAT.Readers.Manager_Base'Class) is
      Memory_Reader : constant MAT.Memory.Readers.Memory_Reader_Access
        := new MAT.Memory.Readers.Memory_Servant;
   begin
      Memory.Reader := Memory_Reader.all'Access;
      Memory_Reader.Data := Memory'Unrestricted_Access;
      MAT.Memory.Readers.Register (Reader, Memory_Reader);
   end Initialize;

   --  ------------------------------
   --  Take into account a malloc probe.  The memory slot [Addr .. Slot.Size] is inserted
   --  in the used slots map.  The freed slots that intersect the malloc'ed region are
   --  removed from the freed map.
   --  ------------------------------
   procedure Probe_Malloc (Memory : in out Target_Memory;
                           Addr   : in MAT.Types.Target_Addr;
                           Slot   : in Allocation) is
   begin
      Memory.Memory.Probe_Malloc (Addr, Slot);
   end Probe_Malloc;

   --  ------------------------------
   --  Take into account a free probe.  Add the memory slot in the freed map and remove
   --  the slot from the used slots map.
   --  ------------------------------
   procedure Probe_Free (Memory : in out Target_Memory;
                         Addr   : in MAT.Types.Target_Addr;
                         Slot   : in Allocation) is
   begin
      Memory.Memory.Probe_Free (Addr, Slot);
   end Probe_Free;

   --  ------------------------------
   --  Take into account a realloc probe.  The old memory slot represented by Old_Addr is
   --  removed from the used slots maps and the new memory slot [Addr .. Slot.Size] is
   --  inserted in the used slots map.
   --  ------------------------------
   procedure Probe_Realloc (Memory : in out Target_Memory;
                            Addr     : in MAT.Types.Target_Addr;
                            Old_Addr : in MAT.Types.Target_Addr;
                            Slot     : in Allocation) is
   begin
      Memory.Memory.Probe_Realloc (Addr, Old_Addr, Slot);
   end Probe_Realloc;

   --  ------------------------------
   --  Insert in the frame tree the new stack frame represented by <tt>Pc</tt>.
   --  If the frame is already known, the frame reference counter is incremented.
   --  The frame represented by <tt>Pc</tt> is returned in <tt>Result</tt>.
   --  ------------------------------
   procedure Create_Frame (Memory : in out Target_Memory;
                           Pc     : in MAT.Frames.Frame_Table;
                           Result : out MAT.Frames.Frame_Type) is
   begin
      Memory.Memory.Create_Frame (Pc, Result);
   end Create_Frame;

   --  ------------------------------
   --  Collect the information about memory slot sizes allocated by the application.
   --  ------------------------------
   procedure Size_Information (Memory : in out Target_Memory;
                               Sizes  : in out MAT.Memory.Tools.Size_Info_Map) is
   begin
      Memory.Memory.Size_Information (Sizes);
   end Size_Information;

   --  ------------------------------
   --  Collect the information about threads and the memory allocations they've made.
   --  ------------------------------
   procedure Thread_Information (Memory  : in out Target_Memory;
                                 Threads : in out Memory_Info_Map) is
   begin
      Memory.Memory.Thread_Information (Threads);
   end Thread_Information;

   --  ------------------------------
   --  Collect the information about frames and the memory allocations they've made.
   --  ------------------------------
   procedure Frame_Information (Memory : in out Target_Memory;
                                Level  : in Natural;
                                Frames : in out Frame_Info_Map) is
   begin
      Memory.Memory.Frame_Information (Level, Frames);
   end Frame_Information;

   --  ------------------------------
   --  Get the global memory and allocation statistics.
   --  ------------------------------
   procedure Stat_Information (Memory : in out Target_Memory;
                               Result : out Memory_Stat) is
   begin
      Memory.Memory.Stat_Information (Result);
   end Stat_Information;

   --  ------------------------------
   --  Find from the <tt>Memory</tt> map the memory slots whose address intersects
   --  the region [From .. To] and which is selected by the given filter expression.
   --  Add the memory slot in the <tt>Into</tt> list if it does not already contains
   --  the memory slot.
   --  ------------------------------
   procedure Find (Memory : in out Target_Memory;
                   From   : in MAT.Types.Target_Addr;
                   To     : in MAT.Types.Target_Addr;
                   Filter : in MAT.Expressions.Expression_Type;
                   Into   : in out MAT.Memory.Allocation_Map) is
   begin
      Memory.Memory.Find (From, To, Filter, Into);
   end Find;

   protected body Memory_Allocator is

      --  ------------------------------
      --  Add the memory region from the list of memory region managed by the program.
      --  ------------------------------
      procedure Add_Region (Region : in Region_Info) is
      begin
         Regions.Insert (Region.Start_Addr, Region);
      end Add_Region;

      --  ------------------------------
      --  Remove the memory region [Addr .. Addr + Size] from the free list.
      --  ------------------------------
      procedure Remove_Free (Addr : in MAT.Types.Target_Addr;
                             Size : in MAT.Types.Target_Size) is
         Iter : Allocation_Cursor;
         Last : constant MAT.Types.Target_Addr := Addr + MAT.Types.Target_Addr (Size);
         Slot : Allocation;
      begin
         --  Walk the list of free blocks and remove all the blocks which intersect the region
         --  [Addr .. Addr + Slot.Size].  We start walking at the first block below and near
         --  the address.  Slots are then removed when they intersect the malloc'ed region.
         Iter := Freed_Slots.Floor (Addr);
         while Allocation_Maps.Has_Element (Iter) loop
            declare
               Freed_Addr : constant MAT.Types.Target_Addr := Allocation_Maps.Key (Iter);
            begin
               exit when Freed_Addr > Last;
               Slot := Allocation_Maps.Element (Iter);
               if Freed_Addr + MAT.Types.Target_Addr (Slot.Size) > Addr then
                  if Stats.Total_Free > Slot.Size then
                     Stats.Total_Free := Stats.Total_Free - Slot.Size;
                  else
                     Stats.Total_Free := 0;
                  end if;
                  Freed_Slots.Delete (Iter);
                  Iter := Freed_Slots.Floor (Addr);
               else
                  Allocation_Maps.Next (Iter);
               end if;
            end;
         end loop;
      end Remove_Free;

      --  ------------------------------
      --  Take into account a malloc probe.  The memory slot [Addr .. Slot.Size] is inserted
      --  in the used slots map.  The freed slots that intersect the malloc'ed region are
      --  removed from the freed map.
      --  ------------------------------
      procedure Probe_Malloc (Addr   : in MAT.Types.Target_Addr;
                              Slot   : in Allocation) is
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Malloc at {0} size {1}", MAT.Types.Hex_Image (Addr),
                       MAT.Types.Target_Size'Image (Slot.Size));
         end if;
         Stats.Malloc_Count := Stats.Malloc_Count + 1;
         Stats.Total_Alloc := Stats.Total_Alloc + Slot.Size;
         Remove_Free (Addr, Slot.Size);
         Used_Slots.Insert (Addr, Slot);
      end Probe_Malloc;

      --  ------------------------------
      --  Take into account a free probe.  Add the memory slot in the freed map and remove
      --  the slot from the used slots map.
      --  ------------------------------
      procedure Probe_Free (Addr   : in MAT.Types.Target_Addr;
                            Slot   : in Allocation) is
         Item : Allocation;
         Iter : Allocation_Cursor;
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Free {0}", MAT.Types.Hex_Image (Addr));
         end if;
         Stats.Free_Count := Stats.Free_Count + 1;
         Iter := Used_Slots.Find (Addr);
         if Allocation_Maps.Has_Element (Iter) then
            Item := Allocation_Maps.Element (Iter);
            if Stats.Total_Alloc >= Item.Size then
               Stats.Total_Alloc := Stats.Total_Alloc - Item.Size;
            else
               Stats.Total_Alloc := 0;
            end if;
            Stats.Total_Free := Stats.Total_Free + Item.Size;
            MAT.Frames.Release (Item.Frame);
            Used_Slots.Delete (Iter);
            Item.Frame := Slot.Frame;
            Freed_Slots.Insert (Addr, Item);
         end if;
      end Probe_Free;

      --  ------------------------------
      --  Take into account a realloc probe.  The old memory slot represented by Old_Addr is
      --  removed from the used slots maps and the new memory slot [Addr .. Slot.Size] is
      --  inserted in the used slots map.
      --  ------------------------------
      procedure Probe_Realloc (Addr     : in MAT.Types.Target_Addr;
                               Old_Addr : in MAT.Types.Target_Addr;
                               Slot     : in Allocation) is
         procedure Update_Size (Key     : in MAT.Types.Target_Addr;
                                Element : in out Allocation);

         procedure Update_Size (Key     : in MAT.Types.Target_Addr;
                                Element : in out Allocation) is
            pragma Unreferenced (Key);
         begin
            if Stats.Total_Alloc >= Element.Size then
               Stats.Total_Alloc := Stats.Total_Alloc - Element.Size;
            else
               Stats.Total_Alloc := 0;
            end if;
            Element.Size := Slot.Size;
            MAT.Frames.Release (Element.Frame);
            Element.Frame := Slot.Frame;
         end Update_Size;

         Pos      : Allocation_Cursor;
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Realloc {0} to {1} size {2}", MAT.Types.Hex_Image (Old_Addr),
                       MAT.Types.Hex_Image (Addr), MAT.Types.Target_Size'Image (Slot.Size));
         end if;
         Stats.Realloc_Count := Stats.Realloc_Count + 1;
         if Addr /= 0 then
            Stats.Total_Alloc := Stats.Total_Alloc + Slot.Size;
            Pos := Used_Slots.Find (Old_Addr);
            if Allocation_Maps.Has_Element (Pos) then
               if Addr = Old_Addr then
                  Used_Slots.Update_Element (Pos, Update_Size'Access);
               else
                  Used_Slots.Delete (Pos);
                  Used_Slots.Insert (Addr, Slot);
               end if;
            else
               Used_Slots.Insert (Addr, Slot);
            end if;
            Remove_Free (Addr, Slot.Size);
         end if;
      end Probe_Realloc;

      --  ------------------------------
      --  Insert in the frame tree the new stack frame represented by <tt>Pc</tt>.
      --  If the frame is already known, the frame reference counter is incremented.
      --  The frame represented by <tt>Pc</tt> is returned in <tt>Result</tt>.
      --  ------------------------------
      procedure Create_Frame (Pc     : in MAT.Frames.Frame_Table;
                              Result : out MAT.Frames.Frame_Type) is
      begin
         MAT.Frames.Insert (Frames, Pc, Result);
      end Create_Frame;

      --  ------------------------------
      --  Collect the information about memory slot sizes allocated by the application.
      --  ------------------------------
      procedure Size_Information (Sizes  : in out MAT.Memory.Tools.Size_Info_Map) is
      begin
         MAT.Memory.Tools.Size_Information (Used_Slots, Sizes);
      end Size_Information;

      --  ------------------------------
      --  Collect the information about threads and the memory allocations they've made.
      --  ------------------------------
      procedure Thread_Information (Threads : in out Memory_Info_Map) is
      begin
         MAT.Memory.Tools.Thread_Information (Used_Slots, Threads);
      end Thread_Information;

      --  ------------------------------
      --  Collect the information about frames and the memory allocations they've made.
      --  ------------------------------
      procedure Frame_Information (Level  : in Natural;
                                   Frames : in out Frame_Info_Map) is
      begin
         MAT.Memory.Tools.Frame_Information (Used_Slots, Level, Frames);
      end Frame_Information;

      --  ------------------------------
      --  Find from the <tt>Memory</tt> map the memory slots whose address intersects
      --  the region [From .. To] and which is selected by the given filter expression.
      --  Add the memory slot in the <tt>Into</tt> list if it does not already contains
      --  the memory slot.
      --  ------------------------------
      procedure Find (From   : in MAT.Types.Target_Addr;
                      To     : in MAT.Types.Target_Addr;
                      Filter : in MAT.Expressions.Expression_Type;
                      Into   : in out MAT.Memory.Allocation_Map) is
      begin
         MAT.Memory.Tools.Find (Used_Slots, From, To, Filter, Into);
      end Find;

      --  ------------------------------
      --  Get the global memory and allocation statistics.
      --  ------------------------------
      procedure Stat_Information (Result : out Memory_Stat) is
      begin
         Result := Stats;
      end Stat_Information;

   end Memory_Allocator;

end MAT.Memory.Targets;

-----------------------------------------------------------------------
--  Memory Events - Definition and Analysis of memory events
--  Copyright (C) 2014 Stephane Carrez
--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.
-----------------------------------------------------------------------
with Util.Log.Loggers;

with MAT.Memory.Readers;
package body MAT.Memory.Targets is

   --  The logger
   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("MAT.Memory.Targets");

   --  ------------------------------
   --  Initialize the target memory object to manage the memory slots, the stack frames
   --  and setup the reader to analyze the memory events.
   --  ------------------------------
   procedure Initialize (Memory : in out Target_Memory;
                         Reader : in out MAT.Readers.Manager_Base'Class) is
      Memory_Reader : constant MAT.Memory.Readers.Memory_Reader_Access
        := new MAT.Memory.Readers.Memory_Servant;
   begin
      Memory.Reader := Memory_Reader.all'Access;
      Memory_Reader.Data := Memory'Unrestricted_Access;
      MAT.Memory.Readers.Register (Reader, Memory_Reader);
   end Initialize;

   --  ------------------------------
   --  Add the memory region from the list of memory region managed by the program.
   --  ------------------------------
   procedure Add_Region (Memory : in out Target_Memory;
                         Region : in Region_Info) is
   begin
      Memory.Memory.Add_Region (Region);
   end Add_Region;

   --  ------------------------------
   --  Take into account a malloc probe.  The memory slot [Addr .. Slot.Size] is inserted
   --  in the used slots map.  The freed slots that intersect the malloc'ed region are
   --  removed from the freed map.
   --  ------------------------------
   procedure Probe_Malloc (Memory : in out Target_Memory;
                           Addr   : in MAT.Types.Target_Addr;
                           Slot   : in Allocation) is
   begin
      Memory.Memory.Probe_Malloc (Addr, Slot);
   end Probe_Malloc;

   --  ------------------------------
   --  Take into account a free probe.  Add the memory slot in the freed map and remove
   --  the slot from the used slots map.
   --  ------------------------------
   procedure Probe_Free (Memory : in out Target_Memory;
                         Addr   : in MAT.Types.Target_Addr;
                         Slot   : in Allocation) is
   begin
      Memory.Memory.Probe_Free (Addr, Slot);
   end Probe_Free;

   --  ------------------------------
   --  Take into account a realloc probe.  The old memory slot represented by Old_Addr is
   --  removed from the used slots maps and the new memory slot [Addr .. Slot.Size] is
   --  inserted in the used slots map.
   --  ------------------------------
   procedure Probe_Realloc (Memory : in out Target_Memory;
                            Addr     : in MAT.Types.Target_Addr;
                            Old_Addr : in MAT.Types.Target_Addr;
                            Slot     : in Allocation) is
   begin
      Memory.Memory.Probe_Realloc (Addr, Old_Addr, Slot);
   end Probe_Realloc;

   --  ------------------------------
   --  Insert in the frame tree the new stack frame represented by <tt>Pc</tt>.
   --  If the frame is already known, the frame reference counter is incremented.
   --  The frame represented by <tt>Pc</tt> is returned in <tt>Result</tt>.
   --  ------------------------------
   procedure Create_Frame (Memory : in out Target_Memory;
                           Pc     : in MAT.Frames.Frame_Table;
                           Result : out MAT.Frames.Frame_Type) is
   begin
      Memory.Memory.Create_Frame (Pc, Result);
   end Create_Frame;

   --  ------------------------------
   --  Collect the information about memory slot sizes allocated by the application.
   --  ------------------------------
   procedure Size_Information (Memory : in out Target_Memory;
                               Sizes  : in out MAT.Memory.Tools.Size_Info_Map) is
   begin
      Memory.Memory.Size_Information (Sizes);
   end Size_Information;

   --  ------------------------------
   --  Collect the information about threads and the memory allocations they've made.
   --  ------------------------------
   procedure Thread_Information (Memory  : in out Target_Memory;
                                 Threads : in out Memory_Info_Map) is
   begin
      Memory.Memory.Thread_Information (Threads);
   end Thread_Information;

   --  ------------------------------
   --  Collect the information about frames and the memory allocations they've made.
   --  ------------------------------
   procedure Frame_Information (Memory : in out Target_Memory;
                                Level  : in Natural;
                                Frames : in out Frame_Info_Map) is
   begin
      Memory.Memory.Frame_Information (Level, Frames);
   end Frame_Information;

   --  ------------------------------
   --  Get the global memory and allocation statistics.
   --  ------------------------------
   procedure Stat_Information (Memory : in out Target_Memory;
                               Result : out Memory_Stat) is
   begin
      Memory.Memory.Stat_Information (Result);
   end Stat_Information;

   --  ------------------------------
   --  Find from the <tt>Memory</tt> map the memory slots whose address intersects
   --  the region [From .. To] and which is selected by the given filter expression.
   --  Add the memory slot in the <tt>Into</tt> list if it does not already contains
   --  the memory slot.
   --  ------------------------------
   procedure Find (Memory : in out Target_Memory;
                   From   : in MAT.Types.Target_Addr;
                   To     : in MAT.Types.Target_Addr;
                   Filter : in MAT.Expressions.Expression_Type;
                   Into   : in out MAT.Memory.Allocation_Map) is
   begin
      Memory.Memory.Find (From, To, Filter, Into);
   end Find;

   protected body Memory_Allocator is

      --  ------------------------------
      --  Add the memory region from the list of memory region managed by the program.
      --  ------------------------------
      procedure Add_Region (Region : in Region_Info) is
      begin
         Regions.Insert (Region.Start_Addr, Region);
      end Add_Region;

      --  ------------------------------
      --  Remove the memory region [Addr .. Addr + Size] from the free list.
      --  ------------------------------
      procedure Remove_Free (Addr : in MAT.Types.Target_Addr;
                             Size : in MAT.Types.Target_Size) is
         Iter : Allocation_Cursor;
         Last : constant MAT.Types.Target_Addr := Addr + MAT.Types.Target_Addr (Size);
         Slot : Allocation;
      begin
         --  Walk the list of free blocks and remove all the blocks which intersect the region
         --  [Addr .. Addr + Slot.Size].  We start walking at the first block below and near
         --  the address.  Slots are then removed when they intersect the malloc'ed region.
         Iter := Freed_Slots.Floor (Addr);
         while Allocation_Maps.Has_Element (Iter) loop
            declare
               Freed_Addr : constant MAT.Types.Target_Addr := Allocation_Maps.Key (Iter);
            begin
               exit when Freed_Addr > Last;
               Slot := Allocation_Maps.Element (Iter);
               if Freed_Addr + MAT.Types.Target_Addr (Slot.Size) > Addr then
                  if Stats.Total_Free > Slot.Size then
                     Stats.Total_Free := Stats.Total_Free - Slot.Size;
                  else
                     Stats.Total_Free := 0;
                  end if;
                  Freed_Slots.Delete (Iter);
                  Iter := Freed_Slots.Floor (Addr);
               else
                  Allocation_Maps.Next (Iter);
               end if;
            end;
         end loop;
      end Remove_Free;

      --  ------------------------------
      --  Take into account a malloc probe.  The memory slot [Addr .. Slot.Size] is inserted
      --  in the used slots map.  The freed slots that intersect the malloc'ed region are
      --  removed from the freed map.
      --  ------------------------------
      procedure Probe_Malloc (Addr   : in MAT.Types.Target_Addr;
                              Slot   : in Allocation) is
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Malloc at {0} size {1}", MAT.Types.Hex_Image (Addr),
                       MAT.Types.Target_Size'Image (Slot.Size));
         end if;
         Stats.Malloc_Count := Stats.Malloc_Count + 1;
         Stats.Total_Alloc := Stats.Total_Alloc + Slot.Size;
         Remove_Free (Addr, Slot.Size);
         Used_Slots.Insert (Addr, Slot);
      end Probe_Malloc;

      --  ------------------------------
      --  Take into account a free probe.  Add the memory slot in the freed map and remove
      --  the slot from the used slots map.
      --  ------------------------------
      procedure Probe_Free (Addr   : in MAT.Types.Target_Addr;
                            Slot   : in Allocation) is
         Item : Allocation;
         Iter : Allocation_Cursor;
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Free {0}", MAT.Types.Hex_Image (Addr));
         end if;
         Stats.Free_Count := Stats.Free_Count + 1;
         Iter := Used_Slots.Find (Addr);
         if Allocation_Maps.Has_Element (Iter) then
            Item := Allocation_Maps.Element (Iter);
            if Stats.Total_Alloc >= Item.Size then
               Stats.Total_Alloc := Stats.Total_Alloc - Item.Size;
            else
               Stats.Total_Alloc := 0;
            end if;
            Stats.Total_Free := Stats.Total_Free + Item.Size;
            MAT.Frames.Release (Item.Frame);
            Used_Slots.Delete (Iter);
            Item.Frame := Slot.Frame;
            Freed_Slots.Insert (Addr, Item);
         end if;
      end Probe_Free;

      --  ------------------------------
      --  Take into account a realloc probe.  The old memory slot represented by Old_Addr is
      --  removed from the used slots maps and the new memory slot [Addr .. Slot.Size] is
      --  inserted in the used slots map.
      --  ------------------------------
      procedure Probe_Realloc (Addr     : in MAT.Types.Target_Addr;
                               Old_Addr : in MAT.Types.Target_Addr;
                               Slot     : in Allocation) is
         procedure Update_Size (Key     : in MAT.Types.Target_Addr;
                                Element : in out Allocation);

         procedure Update_Size (Key     : in MAT.Types.Target_Addr;
                                Element : in out Allocation) is
            pragma Unreferenced (Key);
         begin
            if Stats.Total_Alloc >= Element.Size then
               Stats.Total_Alloc := Stats.Total_Alloc - Element.Size;
            else
               Stats.Total_Alloc := 0;
            end if;
            Element.Size := Slot.Size;
            MAT.Frames.Release (Element.Frame);
            Element.Frame := Slot.Frame;
         end Update_Size;

         Pos      : Allocation_Cursor;
      begin
         if Log.Get_Level = Util.Log.DEBUG_LEVEL then
            Log.Debug ("Realloc {0} to {1} size {2}", MAT.Types.Hex_Image (Old_Addr),
                       MAT.Types.Hex_Image (Addr), MAT.Types.Target_Size'Image (Slot.Size));
         end if;
         Stats.Realloc_Count := Stats.Realloc_Count + 1;
         if Addr /= 0 then
            Stats.Total_Alloc := Stats.Total_Alloc + Slot.Size;
            Pos := Used_Slots.Find (Old_Addr);
            if Allocation_Maps.Has_Element (Pos) then
               if Addr = Old_Addr then
                  Used_Slots.Update_Element (Pos, Update_Size'Access);
               else
                  Used_Slots.Delete (Pos);
                  Used_Slots.Insert (Addr, Slot);
               end if;
            else
               Used_Slots.Insert (Addr, Slot);
            end if;
            Remove_Free (Addr, Slot.Size);
         end if;
      end Probe_Realloc;

      --  ------------------------------
      --  Insert in the frame tree the new stack frame represented by <tt>Pc</tt>.
      --  If the frame is already known, the frame reference counter is incremented.
      --  The frame represented by <tt>Pc</tt> is returned in <tt>Result</tt>.
      --  ------------------------------
      procedure Create_Frame (Pc     : in MAT.Frames.Frame_Table;
                              Result : out MAT.Frames.Frame_Type) is
      begin
         MAT.Frames.Insert (Frames, Pc, Result);
      end Create_Frame;

      --  ------------------------------
      --  Collect the information about memory slot sizes allocated by the application.
      --  ------------------------------
      procedure Size_Information (Sizes  : in out MAT.Memory.Tools.Size_Info_Map) is
      begin
         MAT.Memory.Tools.Size_Information (Used_Slots, Sizes);
      end Size_Information;

      --  ------------------------------
      --  Collect the information about threads and the memory allocations they've made.
      --  ------------------------------
      procedure Thread_Information (Threads : in out Memory_Info_Map) is
      begin
         MAT.Memory.Tools.Thread_Information (Used_Slots, Threads);
      end Thread_Information;

      --  ------------------------------
      --  Collect the information about frames and the memory allocations they've made.
      --  ------------------------------
      procedure Frame_Information (Level  : in Natural;
                                   Frames : in out Frame_Info_Map) is
      begin
         MAT.Memory.Tools.Frame_Information (Used_Slots, Level, Frames);
      end Frame_Information;

      --  ------------------------------
      --  Find from the <tt>Memory</tt> map the memory slots whose address intersects
      --  the region [From .. To] and which is selected by the given filter expression.
      --  Add the memory slot in the <tt>Into</tt> list if it does not already contains
      --  the memory slot.
      --  ------------------------------
      procedure Find (From   : in MAT.Types.Target_Addr;
                      To     : in MAT.Types.Target_Addr;
                      Filter : in MAT.Expressions.Expression_Type;
                      Into   : in out MAT.Memory.Allocation_Map) is
      begin
         MAT.Memory.Tools.Find (Used_Slots, From, To, Filter, Into);
      end Find;

      --  ------------------------------
      --  Get the global memory and allocation statistics.
      --  ------------------------------
      procedure Stat_Information (Result : out Memory_Stat) is
      begin
         Result := Stats;
      end Stat_Information;

   end Memory_Allocator;

end MAT.Memory.Targets;

Implement the Add_Region procedure

Implement the Add_Region procedure