-----------------------------------------------------------------------
--  wiki-strings -- Wiki string types and operations
--  Copyright (C) 2016, 2017, 2020, 2022 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 Wiki.Helpers;
package body Wiki.Strings is

   --  ------------------------------
   --  Search for the first occurrence of the character in the builder and
   --  starting after the from index.  Returns the index of the first occurence or 0.
   --  ------------------------------
   function Index (Source : in BString;
                   Char   : in WChar;
                   From   : in Positive := 1) return Natural is
      function Find (Content : in WString) return Natural;

      function Find (Content : in WString) return Natural is
      begin
         for I in Content'Range loop
            if Content (I) = Char then
               return I;
            end if;
         end loop;
         return 0;
      end Find;

      function Find_Builder is
         new Wide_Wide_Builders.Find (Find);

   begin
      return Find_Builder (Source, From);
   end Index;

   --  ------------------------------
   --  Find the last position of the character in the string and starting
   --  at the given position.  Stop at the first character different than `Char`.
   --  ------------------------------
   function Last_Position (Source : in Bstring;
                           Char   : in WChar;
                           From   : in Positive := 1) return Natural is

      function Find (Content : in WString) return Natural;

      function Find (Content : in WString) return Natural is
      begin
         for I in Content'Range loop
            if Content (I) /= Char then
               return I;
            end if;
         end loop;
         return 0;
      end Find;

      function Find_Builder is
         new Wide_Wide_Builders.Find (Find);

   begin
      return Find_Builder (Source, From);
   end Last_Position;

   --  ------------------------------
   --  Count the the number of consecutive occurence of the given character
   --  and starting at the given position.
   --  ------------------------------
   function Count_Occurence (Source : in Bstring;
                             Char   : in WChar;
                             From   : in Positive := 1) return Natural is
      Pos : constant Natural := Last_Position (Source, Char, From);
   begin
      if Pos > From then
         return Pos - From;
      else
         return 0;
      end if;
   end Count_Occurence;

   function Skip_Spaces (Source : in Bstring;
                         From   : in Positive;
                         Last   : in Positive) return Positive is
      Pos : Positive := From;
   begin
      while Pos <= Last and then Helpers.Is_Space_Or_Newline (Element (Source, Pos)) loop
         Pos := Pos + 1;
      end loop;
      return Pos;
   end Skip_Spaces;

end Wiki.Strings;

-----------------------------------------------------------------------
--  wiki-strings -- Wiki string types and operations
--  Copyright (C) 2016, 2017, 2020, 2022 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 Wiki.Helpers;
package body Wiki.Strings is

   --  ------------------------------
   --  Search for the first occurrence of the character in the builder and
   --  starting after the from index.  Returns the index of the first occurence or 0.
   --  ------------------------------
   function Index (Source : in BString;
                   Char   : in WChar;
                   From   : in Positive := 1) return Natural is
      function Find (Content : in WString) return Natural;

      function Find (Content : in WString) return Natural is
      begin
         for I in Content'Range loop
            if Content (I) = Char then
               return I;
            end if;
         end loop;
         return 0;
      end Find;

      function Find_Builder is
         new Wide_Wide_Builders.Find (Find);

   begin
      return Find_Builder (Source, From);
   end Index;

   --  ------------------------------
   --  Find the last position of the character in the string and starting
   --  at the given position.  Stop at the first character different than `Char`.
   --  ------------------------------
   function Last_Position (Source : in BString;
                           Char   : in WChar;
                           From   : in Positive := 1) return Natural is

      function Find (Content : in WString) return Natural;

      function Find (Content : in WString) return Natural is
      begin
         for I in Content'Range loop
            if Content (I) /= Char then
               return I;
            end if;
         end loop;
         return 0;
      end Find;

      function Find_Builder is
         new Wide_Wide_Builders.Find (Find);

   begin
      return Find_Builder (Source, From);
   end Last_Position;

   --  ------------------------------
   --  Count the the number of consecutive occurence of the given character
   --  and starting at the given position.
   --  ------------------------------
   function Count_Occurence (Source : in BString;
                             Char   : in WChar;
                             From   : in Positive := 1) return Natural is
      Pos : constant Natural := Last_Position (Source, Char, From);
   begin
      if Pos > From then
         return Pos - From;
      else
         return 0;
      end if;
   end Count_Occurence;

   function Count_Occurence (Source : in WString;
                             Char   : in WChar;
                             From   : in Positive := 1) return Natural is
      Pos : Positive := From;
   begin
      while Pos <= Source'Last and then Source (Pos) = Char loop
         Pos := Pos + 1;
      end loop;
      return Pos - From;
   end Count_Occurence;

   function Skip_Spaces (Source : in BString;
                         From   : in Positive;
                         Last   : in Positive) return Positive is
      Pos : Positive := From;
   begin
      while Pos <= Last and then Helpers.Is_Space_Or_Newline (Element (Source, Pos)) loop
         Pos := Pos + 1;
      end loop;
      return Pos;
   end Skip_Spaces;

   procedure Scan_Line_Fragment (Source : in BString;
                                 Process : not null
                                    access procedure (Text   : in WString;
                                                      Offset : in Natural)) is

      Offset : Natural := 0;

      procedure Parse_Line_Fragment (Content : in Wiki.Strings.WString) is
      begin
         Process (Content, Offset);
         Offset := Offset + Content'Length;
      end Parse_Line_Fragment;

      procedure Parse_Line_Fragment is
         new Wiki.Strings.Wide_Wide_Builders.Get (Parse_Line_Fragment);
      pragma Inline (Parse_Line_Fragment);

   begin
      Parse_Line_Fragment (Source);
   end Scan_Line_Fragment;

end Wiki.Strings;

Add new operations for the strings

Add new operations for the strings


-----------------------------------------------------------------------
--  awa-tags-modules -- Module awa-tags
--  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.
-----------------------------------------------------------------------

with ADO.Sessions;
with ADO.Sessions.Entities;
with ADO.Statements;
with ADO.Queries;
with ADO.SQL;

with Security.Permissions;

with AWA.Permissions;
with AWA.Services.Contexts;
with AWA.Modules.Get;
with AWA.Modules.Beans;
with AWA.Users.Models;
with AWA.Tags.Models;
with AWA.Tags.Beans;
with AWA.Tags.Components;

with Util.Log.Loggers;
package body AWA.Tags.Modules is

   package ASC renames AWA.Services.Contexts;

   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("AWA.Tags.Module");

   package Register is new AWA.Modules.Beans (Module        => Tag_Module,
                                              Module_Access => Tag_Module_Access);

   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.
   procedure Add_Tag (Session     : in out ADO.Sessions.Master_Session;
                      Id          : in ADO.Identifier;
                      Entity_Type : in ADO.Entity_Type;
                      Tag         : in String);

   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   procedure Remove_Tag (Session     : in out ADO.Sessions.Master_Session;
                         Id          : in ADO.Identifier;
                         Entity_Type : in ADO.Entity_Type;
                         Tag         : in String);

   --  ------------------------------
   --  Initialize the tags module.
   --  ------------------------------
   overriding
   procedure Initialize (Plugin : in out Tag_Module;
                         App    : in AWA.Modules.Application_Access;
                         Props  : in ASF.Applications.Config) is
   begin
      Log.Info ("Initializing the awa-tags module");

      App.Add_Components (AWA.Tags.Components.Definition);

      --  Register the tag list bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_List_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_List_Bean'Access);

      --  Register the tag search bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_Search_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_Search_Bean'Access);

      --  Register the tag info list bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_Info_List_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_Info_List_Bean'Access);

      AWA.Modules.Module (Plugin).Initialize (App, Props);

      --  Add here the creation of manager instances.
   end Initialize;

   --  ------------------------------
   --  Get the tags module.
   --  ------------------------------
   function Get_Tag_Module return Tag_Module_Access is
      function Get is new AWA.Modules.Get (Tag_Module, Tag_Module_Access, NAME);
   begin
      return Get;
   end Get_Tag_Module;

   --  ------------------------------
   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.  The permission represented by <tt>Permission</tt> is checked
   --  to make sure the current user can add the tag.  If the permission is granted, the
   --  tag represented by <tt>Tag</tt> is associated with the said database entity.
   --  ------------------------------
   procedure Add_Tag (Model       : in Tag_Module;
                      Id          : in ADO.Identifier;
                      Entity_Type : in String;
                      Permission  : in String;
                      Tag         : in String) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Log.Info ("User {0} add tag {1} on {2}",
                ADO.Identifier'Image (User.Get_Id), Tag, Ident);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);
      Add_Tag (DB, Id, Kind, Tag);
      Ctx.Commit;
   end Add_Tag;

   --  ------------------------------
   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  The permission represented by <tt>Permission</tt> is checked to make sure the current user
   --  can remove the tag.
   --  ------------------------------
   procedure Remove_Tag (Model       : in Tag_Module;
                         Id          : in ADO.Identifier;
                         Entity_Type : in String;
                         Permission  : in String;
                         Tag         : in String) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Log.Info ("User {0} removes tag {1} on {2}",
                ADO.Identifier'Image (User.Get_Id), Tag, Ident);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);
      Remove_Tag (DB, Id, Kind, Tag);
      Ctx.Commit;
   end Remove_Tag;

   --  ------------------------------
   --  Remove the tags defined by the <tt>Deleted</tt> tag list and add the tags defined
   --  in the <tt>Added</tt> tag list.  The tags are associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  The permission represented by <tt>Permission</tt> is checked to make sure the current user
   --  can remove or add the tag.
   --  ------------------------------
   procedure Update_Tags (Model       : in Tag_Module;
                          Id          : in ADO.Identifier;
                          Entity_Type : in String;
                          Permission  : in String;
                          Added       : in Util.Strings.Vectors.Vector;
                          Deleted     : in Util.Strings.Vectors.Vector) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
      Iter   : Util.Strings.Vectors.Cursor;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);

      --  Delete the tags that have been removed.
      Iter := Deleted.First;
      while Util.Strings.Vectors.Has_Element (Iter) loop
         declare
            Tag : constant String := Util.Strings.Vectors.Element (Iter);
         begin
            Log.Info ("User {0} removes tag {1} on {2}",
                      ADO.Identifier'Image (User.Get_Id), Tag, Ident);

            Remove_Tag (DB, Id, Kind, Tag);
         end;
         Util.Strings.Vectors.Next (Iter);
      end loop;

      --  And add the new ones.
      Iter := Added.First;
      while Util.Strings.Vectors.Has_Element (Iter) loop
         declare
            Tag : constant String := Util.Strings.Vectors.Element (Iter);
         begin
            Log.Info ("User {0} adds tag {1} on {2}",
                      ADO.Identifier'Image (User.Get_Id), Tag, Ident);

            Add_Tag (DB, Id, Kind, Tag);
         end;
         Util.Strings.Vectors.Next (Iter);
      end loop;
      Ctx.Commit;
   end Update_Tags;

   --  ------------------------------
   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.
   --  ------------------------------
   procedure Add_Tag (Session     : in out ADO.Sessions.Master_Session;
                      Id          : in ADO.Identifier;
                      Entity_Type : in ADO.Entity_Type;
                      Tag         : in String) is
      Query    : ADO.Queries.Context;
      Tag_Info : AWA.Tags.Models.Tag_Ref;
      Tag_Link : AWA.Tags.Models.Tagged_Entity_Ref;
   begin
      Query.Set_Query (AWA.Tags.Models.Query_Check_Tag);

      declare
         Stmt : ADO.Statements.Query_Statement := Session.Create_Statement (Query);
      begin
         --  Build the query.
         Stmt.Bind_Param (Name => "entity_type", Value => Entity_Type);
         Stmt.Bind_Param (Name => "entity_id", Value => Id);
         Stmt.Bind_Param (Name => "tag", Value => Tag);

         --  Run the query.
         Stmt.Execute;

         if not Stmt.Has_Elements then
            --  The tag is not defined in the database.
            --  Create it and link it to the entity.
            Tag_Info.Set_Name (Tag);
            Tag_Link.Set_Tag (Tag_Info);
            Tag_Link.Set_For_Entity_Id (Id);
            Tag_Link.Set_Entity_Type (Entity_Type);

            Tag_Info.Save (Session);
            Tag_Link.Save (Session);

         elsif Stmt.Is_Null (1) then
            --  The tag is defined but the entity is not linked with it.
            Tag_Info.Set_Id (Stmt.Get_Identifier (0));
            Tag_Link.Set_Tag (Tag_Info);
            Tag_Link.Set_For_Entity_Id (Id);
            Tag_Link.Set_Entity_Type (Entity_Type);
            Tag_Link.Save (Session);
         end if;
      end;
   end Add_Tag;

   --  ------------------------------
   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  ------------------------------
   procedure Remove_Tag (Session     : in out ADO.Sessions.Master_Session;
                         Id          : in ADO.Identifier;
                         Entity_Type : in ADO.Entity_Type;
                         Tag         : in String) is
      Query    : ADO.SQL.Query;
      Tag_Link : AWA.Tags.Models.Tagged_Entity_Ref;
      Found    : Boolean;
   begin
      Query.Set_Join ("INNER JOIN awa_tag AS tag ON tag.id = o.tag_id");
      Query.Set_Filter ("tag.name = :tag AND o.for_entity_id = :entity_id "
                        & "AND o.entity_type = :entity_type");

      --  Build the query.
      Query.Bind_Param (Name => "entity_type", Value => Entity_Type);
      Query.Bind_Param (Name => "entity_id", Value => Id);
      Query.Bind_Param (Name => "tag", Value => Tag);

      Tag_Link.Find (Session, Query, Found);
      if Found then
         Tag_Link.Delete (Session);
      end if;
   end Remove_Tag;

   --  ------------------------------
   --  Find the tag identifier associated with the given tag.
   --  Return NO_IDENTIFIER if there is no such tag.
   --  ------------------------------
   procedure Find_Tag_Id (Session : in out ADO.Sessions.Session'Class;
                          Tag     : in String;
                          Result  : out ADO.Identifier) is
   begin
      if Tag'Length = 0 then
         Result := ADO.NO_IDENTIFIER;
      else
         declare
            Query    : ADO.SQL.Query;
            Found    : Boolean;
            Tag_Info : AWA.Tags.Models.Tag_Ref;
         begin
            Query.Set_Filter ("o.name = ?");
            Query.Bind_Param (1, Tag);
            Tag_Info.Find (Session => Session,
                           Query   => Query,
                           Found   => Found);
            if not Found then
               Result := ADO.NO_IDENTIFIER;
            else
               Result := Tag_Info.Get_Id;
            end if;
         end;
      end if;
   end Find_Tag_Id;

end AWA.Tags.Modules;

-----------------------------------------------------------------------
--  awa-tags-modules -- Module awa-tags
--  Copyright (C) 2013, 2016 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 ADO.Sessions.Entities;
with ADO.Statements;
with ADO.Queries;
with ADO.SQL;

with Security.Permissions;

with AWA.Permissions;
with AWA.Services.Contexts;
with AWA.Modules.Get;
with AWA.Modules.Beans;
with AWA.Users.Models;
with AWA.Tags.Models;
with AWA.Tags.Beans;
with AWA.Tags.Components;

with Util.Log.Loggers;
package body AWA.Tags.Modules is

   package ASC renames AWA.Services.Contexts;

   Log : constant Util.Log.Loggers.Logger := Util.Log.Loggers.Create ("AWA.Tags.Module");

   package Register is new AWA.Modules.Beans (Module        => Tag_Module,
                                              Module_Access => Tag_Module_Access);

   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.
   procedure Add_Tag (Session     : in out ADO.Sessions.Master_Session;
                      Id          : in ADO.Identifier;
                      Entity_Type : in ADO.Entity_Type;
                      Tag         : in String);

   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   procedure Remove_Tag (Session     : in out ADO.Sessions.Master_Session;
                         Id          : in ADO.Identifier;
                         Entity_Type : in ADO.Entity_Type;
                         Tag         : in String);

   --  ------------------------------
   --  Initialize the tags module.
   --  ------------------------------
   overriding
   procedure Initialize (Plugin : in out Tag_Module;
                         App    : in AWA.Modules.Application_Access;
                         Props  : in ASF.Applications.Config) is
   begin
      Log.Info ("Initializing the awa-tags module");

      App.Add_Components (AWA.Tags.Components.Definition);

      --  Register the tag list bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_List_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_List_Bean'Access);

      --  Register the tag search bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_Search_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_Search_Bean'Access);

      --  Register the tag info list bean.
      Register.Register (Plugin => Plugin,
                         Name   => "AWA.Tags.Beans.Tag_Info_List_Bean",
                         Handler => AWA.Tags.Beans.Create_Tag_Info_List_Bean'Access);

      AWA.Modules.Module (Plugin).Initialize (App, Props);

      --  Add here the creation of manager instances.
   end Initialize;

   --  ------------------------------
   --  Get the tags module.
   --  ------------------------------
   function Get_Tag_Module return Tag_Module_Access is
      function Get is new AWA.Modules.Get (Tag_Module, Tag_Module_Access, NAME);
   begin
      return Get;
   end Get_Tag_Module;

   --  ------------------------------
   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.  The permission represented by <tt>Permission</tt> is checked
   --  to make sure the current user can add the tag.  If the permission is granted, the
   --  tag represented by <tt>Tag</tt> is associated with the said database entity.
   --  ------------------------------
   procedure Add_Tag (Model       : in Tag_Module;
                      Id          : in ADO.Identifier;
                      Entity_Type : in String;
                      Permission  : in String;
                      Tag         : in String) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Log.Info ("User {0} add tag {1} on {2}",
                ADO.Identifier'Image (User.Get_Id), Tag, Ident);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);
      Add_Tag (DB, Id, Kind, Tag);
      Ctx.Commit;
   end Add_Tag;

   --  ------------------------------
   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  The permission represented by <tt>Permission</tt> is checked to make sure the current user
   --  can remove the tag.
   --  ------------------------------
   procedure Remove_Tag (Model       : in Tag_Module;
                         Id          : in ADO.Identifier;
                         Entity_Type : in String;
                         Permission  : in String;
                         Tag         : in String) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Log.Info ("User {0} removes tag {1} on {2}",
                ADO.Identifier'Image (User.Get_Id), Tag, Ident);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);
      Remove_Tag (DB, Id, Kind, Tag);
      Ctx.Commit;
   end Remove_Tag;

   --  ------------------------------
   --  Remove the tags defined by the <tt>Deleted</tt> tag list and add the tags defined
   --  in the <tt>Added</tt> tag list.  The tags are associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  The permission represented by <tt>Permission</tt> is checked to make sure the current user
   --  can remove or add the tag.
   --  ------------------------------
   procedure Update_Tags (Model       : in Tag_Module;
                          Id          : in ADO.Identifier;
                          Entity_Type : in String;
                          Permission  : in String;
                          Added       : in Util.Strings.Vectors.Vector;
                          Deleted     : in Util.Strings.Vectors.Vector) is
      pragma Unreferenced (Model);

      Ctx    : constant ASC.Service_Context_Access := ASC.Current;
      User   : constant AWA.Users.Models.User_Ref := Ctx.Get_User;
      Ident  : constant String := Entity_Type & ADO.Identifier'Image (Id);
      DB     : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
      Kind   : ADO.Entity_Type;
      Iter   : Util.Strings.Vectors.Cursor;
   begin
      --  Check that the user has the permission on the given object.
      AWA.Permissions.Check (Permission => Security.Permissions.Get_Permission_Index (Permission),
                             Entity     => Id);

      Ctx.Start;
      Kind := ADO.Sessions.Entities.Find_Entity_Type (DB, Entity_Type);

      --  Delete the tags that have been removed.
      Iter := Deleted.First;
      while Util.Strings.Vectors.Has_Element (Iter) loop
         declare
            Tag : constant String := Util.Strings.Vectors.Element (Iter);
         begin
            Log.Info ("User {0} removes tag {1} on {2}",
                      ADO.Identifier'Image (User.Get_Id), Tag, Ident);

            Remove_Tag (DB, Id, Kind, Tag);
         end;
         Util.Strings.Vectors.Next (Iter);
      end loop;

      --  And add the new ones.
      Iter := Added.First;
      while Util.Strings.Vectors.Has_Element (Iter) loop
         declare
            Tag : constant String := Util.Strings.Vectors.Element (Iter);
         begin
            Log.Info ("User {0} adds tag {1} on {2}",
                      ADO.Identifier'Image (User.Get_Id), Tag, Ident);

            Add_Tag (DB, Id, Kind, Tag);
         end;
         Util.Strings.Vectors.Next (Iter);
      end loop;
      Ctx.Commit;
   end Update_Tags;

   --  ------------------------------
   --  Add a tag on the database entity referenced by <tt>Id</tt> in the table identified
   --  by <tt>Entity_Type</tt>.
   --  ------------------------------
   procedure Add_Tag (Session     : in out ADO.Sessions.Master_Session;
                      Id          : in ADO.Identifier;
                      Entity_Type : in ADO.Entity_Type;
                      Tag         : in String) is
      Query    : ADO.Queries.Context;
      Tag_Info : AWA.Tags.Models.Tag_Ref;
      Tag_Link : AWA.Tags.Models.Tagged_Entity_Ref;
   begin
      Query.Set_Query (AWA.Tags.Models.Query_Check_Tag);

      declare
         Stmt : ADO.Statements.Query_Statement := Session.Create_Statement (Query);
      begin
         --  Build the query.
         Stmt.Bind_Param (Name => "entity_type", Value => Entity_Type);
         Stmt.Bind_Param (Name => "entity_id", Value => Id);
         Stmt.Bind_Param (Name => "tag", Value => Tag);

         --  Run the query.
         Stmt.Execute;

         if not Stmt.Has_Elements then
            --  The tag is not defined in the database.
            --  Create it and link it to the entity.
            Tag_Info.Set_Name (Tag);
            Tag_Link.Set_Tag (Tag_Info);
            Tag_Link.Set_For_Entity_Id (Id);
            Tag_Link.Set_Entity_Type (Entity_Type);

            Tag_Info.Save (Session);
            Tag_Link.Save (Session);

         elsif Stmt.Is_Null (1) then
            --  The tag is defined but the entity is not linked with it.
            Tag_Info.Set_Id (Stmt.Get_Identifier (0));
            Tag_Link.Set_Tag (Tag_Info);
            Tag_Link.Set_For_Entity_Id (Id);
            Tag_Link.Set_Entity_Type (Entity_Type);
            Tag_Link.Save (Session);
         end if;
      end;
   end Add_Tag;

   --  ------------------------------
   --  Remove the tag identified by <tt>Tag</tt> and associated with the database entity
   --  referenced by <tt>Id</tt> in the table identified by <tt>Entity_Type</tt>.
   --  ------------------------------
   procedure Remove_Tag (Session     : in out ADO.Sessions.Master_Session;
                         Id          : in ADO.Identifier;
                         Entity_Type : in ADO.Entity_Type;
                         Tag         : in String) is
      Query    : ADO.SQL.Query;
      Tag_Link : AWA.Tags.Models.Tagged_Entity_Ref;
      Found    : Boolean;
   begin
      Query.Set_Join ("INNER JOIN awa_tag AS tag ON tag.id = o.tag_id");
      Query.Set_Filter ("tag.name = :tag AND o.for_entity_id = :entity_id "
                        & "AND o.entity_type = :entity_type");

      --  Build the query.
      Query.Bind_Param (Name => "entity_type", Value => Entity_Type);
      Query.Bind_Param (Name => "entity_id", Value => Id);
      Query.Bind_Param (Name => "tag", Value => Tag);

      Tag_Link.Find (Session, Query, Found);
      if Found then
         Tag_Link.Delete (Session);
      end if;
   end Remove_Tag;

   --  ------------------------------
   --  Find the tag identifier associated with the given tag.
   --  Return NO_IDENTIFIER if there is no such tag.
   --  ------------------------------
   procedure Find_Tag_Id (Session : in out ADO.Sessions.Session'Class;
                          Tag     : in String;
                          Result  : out ADO.Identifier) is
   begin
      if Tag'Length = 0 then
         Result := ADO.NO_IDENTIFIER;
      else
         declare
            Query    : ADO.SQL.Query;
            Found    : Boolean;
            Tag_Info : AWA.Tags.Models.Tag_Ref;
         begin
            Query.Set_Filter ("o.name = ?");
            Query.Bind_Param (1, Tag);
            Tag_Info.Find (Session => Session,
                           Query   => Query,
                           Found   => Found);
            if not Found then
               Result := ADO.NO_IDENTIFIER;
            else
               Result := Tag_Info.Get_Id;
            end if;
         end;
      end if;
   end Find_Tag_Id;

end AWA.Tags.Modules;

Fix compilation warning

Fix compilation warning


-----------------------------------------------------------------------
--  awa-events -- AWA Events
--  Copyright (C) 2012, 2015, 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.Events;
with Util.Beans.Objects;
with Util.Beans.Basic;
with Util.Beans.Objects.Maps;

with ADO;

with AWA.Index_Arrays;

--  == AWA Events ==
--  The AWA.Events package defines an event framework for modules to post events
--  and have Ada bean methods be invoked when these events are dispatched.  Subscription to
--  events is done through configuration files.  This allows to configure the modules and
--  integrate them together easily at configuration time.
--
--  === Declaration ===
--  Modules define the events that they can generate by instantiating the Definition
--  package. This is a static definition of the event.  Each event is given a unique name.
--
--    with AWA.Events.Definition;
--    ...
--    package Event_New_User is new AWA.Events.Definition ("new-user");
--
--  === Posting an event ===
--  The module can post an event to inform other modules or the system that a particular
--  action occurred.  The module creates the event instance of type Module_Event and
--  populates that event with useful properties for event receivers.
--
--    with AWA.Events;
--    ...
--    Event : AWA.Events.Module_Event;
--
--    Event.Set_Event_Kind (Event_New_User.Kind);
--    Event.Set_Parameter ("email", "harry.potter@hogwarts.org");
--
--  The module will post the event by using the Send_Event operation.
--
--    Manager.Send_Event (Event);
--
--  === Receiving an event ===
--  Modules or applications interested by a particular event will configure the event manager
--  to dispatch the event to an Ada bean event action.  The Ada bean is an object that must
--  implement a procedure that matches the prototype:
--
--    type Action_Bean is new Util.Beans.Basic.Readonly_Bean ...;
--    procedure Action (Bean : in out Action_Bean; Event : in AWA.Events.Module_Event'Class);
--
--  The Ada bean method and object are registered as other Ada beans.
--
--  The configuration file indicates how to bind the Ada bean action and the event together.
--  The action is specified using an EL Method Expression (See Ada EL or JSR 245).
--
--    <on-event name="new_user">
--        <action>#{ada_bean.action}</action>
--    </on-event>
--
--  === Event queues and dispatchers ===
--  The *AWA.Events* framework posts events on queues and it uses a dispatcher to process them.
--  There are two kinds of dispatchers:
--
--    * Synchronous dispatcher process the event when it is posted.  The task which posts
--      the event invokes the Ada bean action.  In this dispatching mode, there is no event queue.
--      If the action method raises an exception, it will however be blocked.
--
--    * Asynchronous dispatcher are executed by dedicated tasks.  The event is put in an event
--      queue.  A dispatcher task processes the event and invokes the action method at a later
--      time.
--
--  When the event is queued, there are two types of event queues:
--
--    * A Fifo memory queue manages the event and dispatches them in FIFO order.
--      If the application is stopped, the events present in the Fifo queue are lost.
--
--    * A persistent event queue manages the event in a similar way as the FIFO queue but
--      saves them in the database.  If the application is stopped, events that have not yet
--      been processed will be dispatched when the application is started again.
--
--  === Data Model ===
--  [images/awa_events_model.png]
--
package AWA.Events is

   type Queue_Index is new Natural;
   type Event_Index is new Natural;

   package Event_Arrays is new AWA.Index_Arrays (Event_Index, String);

   use type Event_Arrays.Element_Type_Access;
   subtype Name_Access is Event_Arrays.Element_Type_Access;

   generic
   package Definition renames Event_Arrays.Definition;

   --  Exception raised if an event name is not found.
   Not_Found : exception renames Event_Arrays.Not_Found;

   --  Find the event runtime index given the event name.
   --  Raises Not_Found exception if the event name is not recognized.
   function Find_Event_Index (Name : in String) return Event_Index renames Event_Arrays.Find;

   --  ------------------------------
   --  Module event
   --  ------------------------------
   type Module_Event is new Util.Events.Event and Util.Beans.Basic.Readonly_Bean with private;
   type Module_Event_Access is access all Module_Event'Class;

   --  Set the event type which identifies the event.
   procedure Set_Event_Kind (Event : in out Module_Event;
                             Kind  : in Event_Index);

   --  Get the event type which identifies the event.
   function Get_Event_Kind (Event : in Module_Event) return Event_Index;

   --  Set a parameter on the message.
   procedure Set_Parameter (Event  : in out Module_Event;
                            Name   : in String;
                            Value  : in String);

   --  Get the parameter with the given name.
   function Get_Parameter (Event : in Module_Event;
                           Name  : in String) return String;

   --  Get the value that corresponds to the parameter with the given name.
   overriding
   function Get_Value (Event : in Module_Event;
                       Name  : in String) return Util.Beans.Objects.Object;

   --  Get the entity identifier associated with the event.
   function Get_Entity_Identifier (Event : in Module_Event) return ADO.Identifier;

   --  Set the entity identifier associated with the event.
   procedure Set_Entity_Identifier (Event : in out Module_Event;
                                    Id    : in ADO.Identifier);

   --  Copy the event properties to the map passed in <tt>Into</tt>.
   procedure Copy (Event : in Module_Event;
                   Into  : in out Util.Beans.Objects.Maps.Map);

private

   type Module_Event is new Util.Events.Event and Util.Beans.Basic.Readonly_Bean with record
      Kind        : Event_Index := Event_Arrays.Invalid_Index;
      Props       : Util.Beans.Objects.Maps.Map;
      Entity      : ADO.Identifier  := ADO.NO_IDENTIFIER;
      Entity_Type : ADO.Entity_Type := ADO.NO_ENTITY_TYPE;
   end record;

   --  The index of the last event definition.
   --  Last_Event : Event_Index := 0;

   --  Get the event type name.
   function Get_Event_Type_Name (Index : in Event_Index) return Name_Access
                                 renames Event_Arrays.Get_Element;

   --  Make and return a copy of the event.
   function Copy (Event : in Module_Event) return Module_Event_Access;

end AWA.Events;

-----------------------------------------------------------------------
--  awa-events -- AWA Events
--  Copyright (C) 2012, 2015, 2018, 2020 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.Events;
with Util.Beans.Objects;
with Util.Beans.Basic;
with Util.Beans.Objects.Maps;
with Util.Properties;

with ADO.Objects;
with ADO.Sessions;

with AWA.Index_Arrays;

--  == AWA Events ==
--  The `AWA.Events` package defines an event framework for modules to post
--  events and have Ada bean methods be invoked when these events are dispatched.
--  Subscription to events is done through configuration files.  This allows to
--  configure the modules and integrate them together easily at configuration time.
--
--  === Declaration ===
--  Modules define the events that they can generate by instantiating the
--  `Definition` package. This is a static definition of the event.  Each event
--  is given a unique name.
--
--    with AWA.Events.Definition;
--    ...
--    package Event_New_User is new AWA.Events.Definition ("new-user");
--
--  === Posting an event ===
--  The module can post an event to inform other modules or the system that
--  a particular action occurred.  The module creates the event instance of
--  type `Module_Event` and populates that event with useful properties for
--  event receivers.
--
--    with AWA.Events;
--    ...
--    Event : AWA.Events.Module_Event;
--
--    Event.Set_Event_Kind (Event_New_User.Kind);
--    Event.Set_Parameter ("email", "harry.potter@hogwarts.org");
--
--  The module will post the event by using the <b>Send_Event</b> operation.
--
--    Manager.Send_Event (Event);
--
--  === Receiving an event ===
--  Modules or applications interested by a particular event will configure
--  the event manager to dispatch the event to an Ada bean event action.
--  The Ada bean is an object that must implement a procedure that matches
--  the prototype:
--
--    type Action_Bean is new Util.Beans.Basic.Readonly_Bean ...;
--    procedure Action (Bean : in out Action_Bean;
--                      Event : in AWA.Events.Module_Event'Class);
--
--  The Ada bean method and object are registered as other Ada beans.
--
--  The configuration file indicates how to bind the Ada bean action and
--  the event together.  The action is specified using an EL Method Expression
--  (See Ada EL or JSR 245).
--
--    <on-event name="new_user">
--        <action>#{ada_bean.action}</action>
--    </on-event>
--
--  === Event queues and dispatchers ===
--  The `AWA.Events` framework posts events on queues and it uses a dispatcher
--  to process them.  There are two kinds of dispatchers:
--
--    * Synchronous dispatcher process the event when it is posted.
--      The task which posts the event invokes the Ada bean action.
--      In this dispatching mode, there is no event queue.
--      If the action method raises an exception, it will however be blocked.
--
--    * Asynchronous dispatcher are executed by dedicated tasks.  The event
--      is put in an event queue.  A dispatcher task processes the event and
--      invokes the action method at a later time.
--
--  When the event is queued, there are two types of event queues:
--
--    * A Fifo memory queue manages the event and dispatches them in FIFO order.
--      If the application is stopped, the events present in the Fifo queue
--      are lost.
--
--    * A persistent event queue manages the event in a similar way as the
--      FIFO queue but saves them in the database.  If the application is
--      stopped, events that have not yet been processed will be dispatched
--      when the application is started again.
--
--  === Data Model ===
--  [images/awa_events_model.png]
--
package AWA.Events is

   type Queue_Index is new Natural;
   type Event_Index is new Natural;

   package Event_Arrays is new AWA.Index_Arrays (Event_Index, String);

   use type Event_Arrays.Element_Type_Access;
   subtype Name_Access is Event_Arrays.Element_Type_Access;

   generic
   package Definition renames Event_Arrays.Definition;

   --  Exception raised if an event name is not found.
   Not_Found : exception renames Event_Arrays.Not_Found;

   --  Find the event runtime index given the event name.
   --  Raises Not_Found exception if the event name is not recognized.
   function Find_Event_Index (Name : in String)
                              return Event_Index renames Event_Arrays.Find;

   --  ------------------------------
   --  Module event
   --  ------------------------------
   type Module_Event is new Util.Events.Event
     and Util.Beans.Basic.Readonly_Bean with private;
   type Module_Event_Access is access all Module_Event'Class;

   --  Set the event type which identifies the event.
   procedure Set_Event_Kind (Event : in out Module_Event;
                             Kind  : in Event_Index);

   --  Get the event type which identifies the event.
   function Get_Event_Kind (Event : in Module_Event) return Event_Index;

   --  Set a parameter on the message.
   procedure Set_Parameter (Event  : in out Module_Event;
                            Name   : in String;
                            Value  : in String);

   --  Get the parameter with the given name.
   function Get_Parameter (Event : in Module_Event;
                           Name  : in String) return String;

   --  Set the parameters of the message.
   procedure Set_Parameters (Event      : in out Module_Event;
                             Parameters : in Util.Beans.Objects.Maps.Map);

   --  Get the value that corresponds to the parameter with the given name.
   overriding
   function Get_Value (Event : in Module_Event;
                       Name  : in String) return Util.Beans.Objects.Object;

   --  Get the entity identifier associated with the event.
   function Get_Entity_Identifier (Event : in Module_Event) return ADO.Identifier;

   --  Set the entity identifier associated with the event.
   procedure Set_Entity_Identifier (Event : in out Module_Event;
                                    Id    : in ADO.Identifier);

   --  Set the database entity associated with the event.
   procedure Set_Entity (Event   : in out Module_Event;
                         Entity  : in ADO.Objects.Object_Ref'Class;
                         Session : in ADO.Sessions.Session'Class);

   --  Copy the event properties to the map passed in `Into`.
   procedure Copy (Event : in Module_Event;
                   Into  : in out Util.Beans.Objects.Maps.Map);

private

   type Module_Event is new Util.Events.Event
     and Util.Beans.Basic.Readonly_Bean with record
      Kind        : Event_Index := Event_Arrays.Invalid_Index;
      Props       : Util.Beans.Objects.Maps.Map;
      Entity      : ADO.Identifier  := ADO.NO_IDENTIFIER;
      Entity_Type : ADO.Entity_Type := ADO.NO_ENTITY_TYPE;
   end record;

   --  The index of the last event definition.
   --  Last_Event : Event_Index := 0;

   --  Get the event type name.
   function Get_Event_Type_Name (Index : in Event_Index) return Name_Access
                                 renames Event_Arrays.Get_Element;

   --  Make and return a copy of the event.
   function Copy (Event : in Module_Event) return Module_Event_Access;

end AWA.Events;

Add Set_Entity and Set_Parameters operations


-----------------------------------------------------------------------
--  awa-workspaces-beans -- Beans for module workspaces
--  Copyright (C) 2011, 2012 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 ASF.Events.Faces.Actions;

with ADO.Sessions;

with AWA.Workspaces.Models;
with AWA.Events.Action_Method;
with AWA.Services.Contexts;
package body AWA.Workspaces.Beans is

   overriding
   procedure Load (Bean : in out Invitation_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Load;

   overriding
   procedure Accept_Invitation (Bean    : in out Invitation_Bean;
                                Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Accept_Invitation;

   overriding
   procedure Send (Bean    : in out Invitation_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Send;

   --  ------------------------------
   --  Example of action method.
   --  ------------------------------
   procedure Action (Bean    : in out Workspaces_Bean;
                     Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Action;

   --  ------------------------------
   --  Event action called to create the workspace when the given event is posted.
   --  ------------------------------
   procedure Create (Bean  : in out Workspaces_Bean;
                     Event : in AWA.Events.Module_Event'Class) is
      pragma Unreferenced (Bean, Event);

      WS  : AWA.Workspaces.Models.Workspace_Ref;
      Ctx : constant AWA.Services.Contexts.Service_Context_Access := AWA.Services.Contexts.Current;
      DB  : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
   begin
      Ctx.Start;
      AWA.Workspaces.Modules.Get_Workspace (Session   => DB,
                                            Context   => Ctx,
                                            Workspace => WS);
      Ctx.Commit;
   end Create;

   package Action_Binding is
     new ASF.Events.Faces.Actions.Action_Method.Bind (Bean   => Workspaces_Bean,
                                                      Method => Action,
                                                      Name   => "action");

   package Create_Binding is
      new AWA.Events.Action_Method.Bind (Name   => "create",
                                         Bean   => Workspaces_Bean,
                                         Method => Create);

   Workspaces_Bean_Binding : aliased constant Util.Beans.Methods.Method_Binding_Array
     := (Action_Binding.Proxy'Access, Create_Binding.Proxy'Access);

   --  ------------------------------
   --  Get the value identified by the name.
   --  ------------------------------
   overriding
   function Get_Value (From : in Workspaces_Bean;
                       Name : in String) return Util.Beans.Objects.Object is
   begin
      if Name = "count" then
         return Util.Beans.Objects.To_Object (From.Count);
      else
         return Util.Beans.Objects.Null_Object;
      end if;
   end Get_Value;

   --  ------------------------------
   --  Set the value identified by the name.
   --  ------------------------------
   overriding
   procedure Set_Value (From  : in out Workspaces_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object) is
   begin
      if Name = "count" then
         From.Count := Util.Beans.Objects.To_Integer (Value);
      end if;
   end Set_Value;

   --  ------------------------------
   --  This bean provides some methods that can be used in a Method_Expression
   --  ------------------------------
   overriding
   function Get_Method_Bindings (From : in Workspaces_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access is
      pragma Unreferenced (From);
   begin
      return Workspaces_Bean_Binding'Access;
   end Get_Method_Bindings;

   --  ------------------------------
   --  Create the Workspaces_Bean bean instance.
   --  ------------------------------
   function Create_Workspaces_Bean (Module : in AWA.Workspaces.Modules.Workspace_Module_Access)
      return Util.Beans.Basic.Readonly_Bean_Access is
      Object : constant Workspaces_Bean_Access := new Workspaces_Bean;
   begin
      Object.Module := Module;
      return Object.all'Access;
   end Create_Workspaces_Bean;

end AWA.Workspaces.Beans;

-----------------------------------------------------------------------
--  awa-workspaces-beans -- Beans for module workspaces
--  Copyright (C) 2011, 2012, 2017 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 ASF.Events.Faces.Actions;

with ADO.Utils;
with ADO.Sessions.Entities;
with ADO.Sessions;
with ADO.Queries;
with ADO.Datasets;

with AWA.Services.Contexts;
with AWA.Workspaces.Models;
with AWA.Events.Action_Method;
with AWA.Services.Contexts;
package body AWA.Workspaces.Beans is

   package ASC renames AWA.Services.Contexts;

   overriding
   procedure Load (Bean : in out Invitation_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Load;

   overriding
   procedure Accept_Invitation (Bean    : in out Invitation_Bean;
                                Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Accept_Invitation;

   overriding
   procedure Send (Bean    : in out Invitation_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Send;

   --  ------------------------------
   --  Example of action method.
   --  ------------------------------
   procedure Action (Bean    : in out Workspaces_Bean;
                     Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
   begin
      null;
   end Action;

   --  ------------------------------
   --  Event action called to create the workspace when the given event is posted.
   --  ------------------------------
   procedure Create (Bean  : in out Workspaces_Bean;
                     Event : in AWA.Events.Module_Event'Class) is
      pragma Unreferenced (Bean, Event);

      WS  : AWA.Workspaces.Models.Workspace_Ref;
      Ctx : constant AWA.Services.Contexts.Service_Context_Access := AWA.Services.Contexts.Current;
      DB  : ADO.Sessions.Master_Session := AWA.Services.Contexts.Get_Master_Session (Ctx);
   begin
      Ctx.Start;
      AWA.Workspaces.Modules.Get_Workspace (Session   => DB,
                                            Context   => Ctx,
                                            Workspace => WS);
      Ctx.Commit;
   end Create;

   package Action_Binding is
     new ASF.Events.Faces.Actions.Action_Method.Bind (Bean   => Workspaces_Bean,
                                                      Method => Action,
                                                      Name   => "action");

   package Create_Binding is
      new AWA.Events.Action_Method.Bind (Name   => "create",
                                         Bean   => Workspaces_Bean,
                                         Method => Create);

   Workspaces_Bean_Binding : aliased constant Util.Beans.Methods.Method_Binding_Array
     := (Action_Binding.Proxy'Access, Create_Binding.Proxy'Access);

   --  ------------------------------
   --  Get the value identified by the name.
   --  ------------------------------
   overriding
   function Get_Value (From : in Workspaces_Bean;
                       Name : in String) return Util.Beans.Objects.Object is
   begin
      if Name = "count" then
         return Util.Beans.Objects.To_Object (From.Count);
      else
         return Util.Beans.Objects.Null_Object;
      end if;
   end Get_Value;

   --  ------------------------------
   --  Set the value identified by the name.
   --  ------------------------------
   overriding
   procedure Set_Value (From  : in out Workspaces_Bean;
                        Name  : in String;
                        Value : in Util.Beans.Objects.Object) is
   begin
      if Name = "count" then
         From.Count := Util.Beans.Objects.To_Integer (Value);
      end if;
   end Set_Value;

   --  ------------------------------
   --  This bean provides some methods that can be used in a Method_Expression
   --  ------------------------------
   overriding
   function Get_Method_Bindings (From : in Workspaces_Bean)
                                 return Util.Beans.Methods.Method_Binding_Array_Access is
      pragma Unreferenced (From);
   begin
      return Workspaces_Bean_Binding'Access;
   end Get_Method_Bindings;

   --  ------------------------------
   --  Create the Workspaces_Bean bean instance.
   --  ------------------------------
   function Create_Workspaces_Bean (Module : in AWA.Workspaces.Modules.Workspace_Module_Access)
      return Util.Beans.Basic.Readonly_Bean_Access is
      Object : constant Workspaces_Bean_Access := new Workspaces_Bean;
   begin
      Object.Module := Module;
      return Object.all'Access;
   end Create_Workspaces_Bean;

   --  ------------------------------
   --  Load the list of members.
   --  ------------------------------
   overriding
   procedure Load (Into    : in out Member_List_Bean;
                   Outcome : in out Ada.Strings.Unbounded.Unbounded_String) is
      Ctx         : constant ASC.Service_Context_Access := ASC.Current;
      User        : constant ADO.Identifier := Ctx.Get_User_Identifier;
      Session     : ADO.Sessions.Session := Into.Module.Get_Session;
      Query       : ADO.Queries.Context;
      Count_Query : ADO.Queries.Context;
      First       : constant Natural  := (Into.Page - 1) * Into.Page_Size;
   begin
      Query.Set_Query (AWA.Workspaces.Models.Query_Workspace_Member_List);
      Count_Query.Set_Count_Query (AWA.Workspaces.Models.Query_Workspace_Member_List);
--        ADO.Sessions.Entities.Bind_Param (Params  => Query,
--                                          Name    => "page_table",
--                                          Table   => AWA.Wikis.Models.WIKI_PAGE_TABLE,
--                                          Session => Session);
      Query.Bind_Param (Name => "user_id", Value => User);
      Count_Query.Bind_Param (Name => "user_id", Value => User);
      AWA.Workspaces.Models.List (Into.Members, Session, Query);
      Into.Count := ADO.Datasets.Get_Count (Session, Count_Query);
   end Load;

end AWA.Workspaces.Beans;

Implement the Load procedure

Implement the Load procedure


-----------------------------------------------------------------------
--  security-filters -- Security filter
--  Copyright (C) 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 ASF.Filters;
with ASF.Requests;
with ASF.Responses;
with ASF.Servlets;
with ASF.Sessions;
with ASF.Principals;
with Security.Permissions;

--  The Security.Filters package defines a servlet filter that can be activated
--  on requests to authenticate users and verify they have the permission to view
--  a page.
package Security.Filters is

   SID_COOKIE : constant String := "SID";

   AID_COOKIE : constant String := "AID";

   type Auth_Filter is new ASF.Filters.Filter with private;

   --  Called by the servlet container to indicate to a servlet that the servlet
   --  is being placed into service.
   procedure Initialize (Server  : in out Auth_Filter;
                         Context : in ASF.Servlets.Servlet_Registry'Class);

   --  Set the permission manager that must be used to verify the permission.
   procedure Set_Permission_Manager (Filter  : in out Auth_Filter;
                                     Manager : in Security.Permissions.Permission_Manager_Access);

   --  Filter the request to make sure the user is authenticated.
   --  Invokes the Do_Login procedure if there is no user.
   --  If a permission manager is defined, check that the user has the permission
   --  to view the page.  Invokes the Do_Deny procedure if the permission
   --  is denied.
   procedure Do_Filter (F        : in Auth_Filter;
                        Request  : in out ASF.Requests.Request'Class;
                        Response : in out ASF.Responses.Response'Class;
                        Chain    : in out ASF.Servlets.Filter_Chain);

   --  Display or redirects the user to the login page.  This procedure is called when
   --  the user is not authenticated.
   procedure Do_Login (F        : in Auth_Filter;
                       Request  : in out ASF.Requests.Request'Class;
                       Response : in out ASF.Responses.Response'Class);

   --  Display the forbidden access page.  This procedure is called when the user is not
   --  authorized to see the page.  The default implementation returns the SC_FORBIDDEN error.
   procedure Do_Deny (F        : in Auth_Filter;
                      Request  : in out ASF.Requests.Request'Class;
                      Response : in out ASF.Responses.Response'Class);

   --  Authenticate a user by using the auto-login cookie.  This procedure is called if the
   --  current session does not have any principal.  Based on the request and the optional
   --  auto-login cookie passed in Auth_Id, it should identify the user and return
   --  a principal object.  The principal object will be freed when the session is closed.
   --  If the user cannot be authenticated, the returned principal should be null.
   --
   --  The default implementation returns a null principal.
   procedure Authenticate (F        : in Auth_Filter;
                           Request  : in out ASF.Requests.Request'Class;
                           Response : in out ASF.Responses.Response'Class;
                           Session  : in ASF.Sessions.Session;
                           Auth_Id  : in String;
                           Principal : out ASF.Principals.Principal_Access);

private

   type Auth_Filter is new ASF.Filters.Filter with record
      Manager : Security.Permissions.Permission_Manager_Access := null;
   end record;

end Security.Filters;

-----------------------------------------------------------------------
--  security-filters -- Security filter
--  Copyright (C) 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 ASF.Filters;
with ASF.Requests;
with ASF.Responses;
with ASF.Servlets;
with ASF.Sessions;
with ASF.Principals;
with Security.Permissions;

--  The Security.Filters package defines a servlet filter that can be activated
--  on requests to authenticate users and verify they have the permission to view
--  a page.
package Security.Filters is

   SID_COOKIE : constant String := "SID";

   AID_COOKIE : constant String := "AID";

   type Auth_Filter is new ASF.Filters.Filter with private;

   --  Called by the servlet container to indicate to a servlet that the servlet
   --  is being placed into service.
   overriding
   procedure Initialize (Server  : in out Auth_Filter;
                         Context : in ASF.Servlets.Servlet_Registry'Class);

   --  Set the permission manager that must be used to verify the permission.
   procedure Set_Permission_Manager (Filter  : in out Auth_Filter;
                                     Manager : in Security.Permissions.Permission_Manager_Access);

   --  Filter the request to make sure the user is authenticated.
   --  Invokes the Do_Login procedure if there is no user.
   --  If a permission manager is defined, check that the user has the permission
   --  to view the page.  Invokes the Do_Deny procedure if the permission
   --  is denied.
   procedure Do_Filter (F        : in Auth_Filter;
                        Request  : in out ASF.Requests.Request'Class;
                        Response : in out ASF.Responses.Response'Class;
                        Chain    : in out ASF.Servlets.Filter_Chain);

   --  Display or redirects the user to the login page.  This procedure is called when
   --  the user is not authenticated.
   procedure Do_Login (F        : in Auth_Filter;
                       Request  : in out ASF.Requests.Request'Class;
                       Response : in out ASF.Responses.Response'Class);

   --  Display the forbidden access page.  This procedure is called when the user is not
   --  authorized to see the page.  The default implementation returns the SC_FORBIDDEN error.
   procedure Do_Deny (F        : in Auth_Filter;
                      Request  : in out ASF.Requests.Request'Class;
                      Response : in out ASF.Responses.Response'Class);

   --  Authenticate a user by using the auto-login cookie.  This procedure is called if the
   --  current session does not have any principal.  Based on the request and the optional
   --  auto-login cookie passed in Auth_Id, it should identify the user and return
   --  a principal object.  The principal object will be freed when the session is closed.
   --  If the user cannot be authenticated, the returned principal should be null.
   --
   --  The default implementation returns a null principal.
   procedure Authenticate (F        : in Auth_Filter;
                           Request  : in out ASF.Requests.Request'Class;
                           Response : in out ASF.Responses.Response'Class;
                           Session  : in ASF.Sessions.Session;
                           Auth_Id  : in String;
                           Principal : out ASF.Principals.Principal_Access);

private

   type Auth_Filter is new ASF.Filters.Filter with record
      Manager : Security.Permissions.Permission_Manager_Access := null;
   end record;

end Security.Filters;

Mark initialize as overriding

Mark initialize as overriding


--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2017 onox <denkpadje@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 GL.Fences;

generic
   type Index_Type is mod <>;
   Maximum_Wait : Duration := 0.010;
package Orka.Rendering.Fences is
   pragma Preelaborate;

   type Buffer_Fence is tagged private;

   type Fence_Status is (Not_Initialized, Signaled, Not_Signaled);

   function Create_Buffer_Fence return Buffer_Fence;

   procedure Prepare_Index (Object : in out Buffer_Fence; Status : out Fence_Status);
   --  Perform a client wait sync for the fence corresponding to the
   --  current index

   procedure Advance_Index (Object : in out Buffer_Fence);
   --  Set a fence for the corresponding index and then increment it

private

   type Fence_Array is array (Index_Type) of GL.Fences.Fence;

   type Buffer_Fence is tagged record
      Fences : Fence_Array;
      Index  : Index_Type;
   end record;

end Orka.Rendering.Fences;

--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2017 onox <denkpadje@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.

private with GL.Fences;

generic
   type Index_Type is mod <>;
   Maximum_Wait : Duration := 0.010;
package Orka.Rendering.Fences is
   pragma Preelaborate;

   type Buffer_Fence is tagged private;

   type Fence_Status is (Not_Initialized, Signaled, Not_Signaled);

   function Create_Buffer_Fence return Buffer_Fence;

   procedure Prepare_Index (Object : in out Buffer_Fence; Status : out Fence_Status);
   --  Perform a client wait sync for the fence corresponding to the
   --  current index

   procedure Advance_Index (Object : in out Buffer_Fence);
   --  Set a fence for the corresponding index and then increment it

private

   type Fence_Array is array (Index_Type) of GL.Fences.Fence;

   type Buffer_Fence is tagged record
      Fences : Fence_Array;
      Index  : Index_Type;
   end record;

end Orka.Rendering.Fences;

orka: Use private with for with'ed unit in Orka.Rendering.Fences

Signed-off-by: onox <34c1d3d2d1347bea60a26f46574de21a7a79b6d5@gmail.com>


-----------------------------------------------------------------------
--  Logs -- Utility Log Package
--  Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
--  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.Exceptions;
with Ada.Strings.Unbounded;

with Util.Log.Appenders;
with Util.Properties;
with Ada.Finalization;
package Util.Log.Loggers is

   use Ada.Exceptions;
   use Ada.Strings.Unbounded;

   --  The logger identifies and configures the log produced
   --  by a component that uses it.  The logger has a name
   --  which can be printed in the log outputs.  The logger instance
   --  contains a log level which can be used to control the level of
   --  logs.
   type Logger is tagged limited private;

   --  Create a logger with the given name.
   function Create (Name : in String) return Logger;

   --  Create a logger with the given name and use the specified level.
   function Create (Name  : in String;
                    Level : in Level_Type) return Logger;

   --  Initialize the logger and create a logger with the given name.
   function Create (Name   : in String;
                    Config : in String) return Logger;

   --  Change the log level
   procedure Set_Level (Log   : in out Logger;
                        Level : in Level_Type);

   --  Get the log level.
   function Get_Level (Log : in Logger) return Level_Type;

   --  Get the log level name.
   function Get_Level_Name (Log : in Logger) return String;

   procedure Print (Log     : in Logger;
                    Level   : in Level_Type;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in Unbounded_String;
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in Unbounded_String;
                    Arg2    : in Unbounded_String;
                    Arg3    : in String := "");

   procedure Info (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in String := "";
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Info (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in Unbounded_String;
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Warn (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in String := "";
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Error (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Error (Log     : in Logger'Class;
                    Message : in String;
                    E       : in Exception_Occurrence);

   --  Set the appender that will handle the log events
   procedure Set_Appender (Log      : in out Logger'Class;
                           Appender : in Util.Log.Appenders.Appender_Access);

   --  Initialize the log environment with the property file.
   procedure Initialize (Name : in String);

   --  Initialize the log environment with the properties.
   procedure Initialize (Properties : in Util.Properties.Manager);

private

   type Logger_Info;
   type Logger_Info_Access is access all Logger_Info;

   type Logger_Info is record
      Next_Logger : Logger_Info_Access;
      Prev_Logger : Logger_Info_Access;
      Level       : Level_Type := INFO_LEVEL;
      Name        : Unbounded_String;
      Appender    : Util.Log.Appenders.Appender_Access;
   end record;

   type Logger is new Ada.Finalization.Limited_Controlled with record
      Name     : Unbounded_String;
      Instance : Logger_Info_Access;
   end record;

   --  Finalize the logger and flush the associated appender
   procedure Finalize (Log : in out Logger);

end Util.Log.Loggers;

-----------------------------------------------------------------------
--  Logs -- Utility Log Package
--  Copyright (C) 2006, 2008, 2009, 2011 Free Software Foundation, Inc.
--  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.Exceptions;
with Ada.Strings.Unbounded;

with Util.Log.Appenders;
with Util.Properties;
with Ada.Finalization;
package Util.Log.Loggers is

   use Ada.Exceptions;
   use Ada.Strings.Unbounded;

   --  The logger identifies and configures the log produced
   --  by a component that uses it.  The logger has a name
   --  which can be printed in the log outputs.  The logger instance
   --  contains a log level which can be used to control the level of
   --  logs.
   type Logger is tagged limited private;
   type Logger_Access is access constant Logger'Class;

   --  Create a logger with the given name.
   function Create (Name : in String) return Logger;

   --  Create a logger with the given name and use the specified level.
   function Create (Name  : in String;
                    Level : in Level_Type) return Logger;

   --  Initialize the logger and create a logger with the given name.
   function Create (Name   : in String;
                    Config : in String) return Logger;

   --  Change the log level
   procedure Set_Level (Log   : in out Logger;
                        Level : in Level_Type);

   --  Get the log level.
   function Get_Level (Log : in Logger) return Level_Type;

   --  Get the log level name.
   function Get_Level_Name (Log : in Logger) return String;

   procedure Print (Log     : in Logger;
                    Level   : in Level_Type;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in Unbounded_String;
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Debug (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in Unbounded_String;
                    Arg2    : in Unbounded_String;
                    Arg3    : in String := "");

   procedure Info (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in String := "";
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Info (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in Unbounded_String;
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Warn (Log     : in Logger'Class;
                   Message : in String;
                   Arg1    : in String := "";
                   Arg2    : in String := "";
                   Arg3    : in String := "");

   procedure Error (Log     : in Logger'Class;
                    Message : in String;
                    Arg1    : in String := "";
                    Arg2    : in String := "";
                    Arg3    : in String := "");

   procedure Error (Log     : in Logger'Class;
                    Message : in String;
                    E       : in Exception_Occurrence);

   --  Set the appender that will handle the log events
   procedure Set_Appender (Log      : in out Logger'Class;
                           Appender : in Util.Log.Appenders.Appender_Access);

   --  Initialize the log environment with the property file.
   procedure Initialize (Name : in String);

   --  Initialize the log environment with the properties.
   procedure Initialize (Properties : in Util.Properties.Manager);

private

   type Logger_Info;
   type Logger_Info_Access is access all Logger_Info;

   type Logger_Info is record
      Next_Logger : Logger_Info_Access;
      Prev_Logger : Logger_Info_Access;
      Level       : Level_Type := INFO_LEVEL;
      Name        : Unbounded_String;
      Appender    : Util.Log.Appenders.Appender_Access;
   end record;

   type Logger is new Ada.Finalization.Limited_Controlled with record
      Name     : Unbounded_String;
      Instance : Logger_Info_Access;
   end record;

   --  Finalize the logger and flush the associated appender
   procedure Finalize (Log : in out Logger);

end Util.Log.Loggers;

Define the Logger_Access type

Define the Logger_Access type


-----------------------------------------------------------------------
--  wiki-render-text -- Wiki Text renderer
--  Copyright (C) 2011, 2012, 2013, 2015, 2016 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 Wiki.Attributes;
with Wiki.Documents;
with Wiki.Streams;
with Wiki.Strings;

--  == Text Renderer ==
--  The <tt>Text_Renderer</tt> allows to render a wiki document into a text content.
--  The formatting rules are ignored except for the paragraphs and sections.
package Wiki.Render.Text is

   --  ------------------------------
   --  Wiki to Text renderer
   --  ------------------------------
   type Text_Renderer is new Wiki.Render.Renderer with private;

   --  Set the output stream.
   procedure Set_Output_Stream (Engine : in out Text_Renderer;
                                Stream : in Streams.Output_Stream_Access);

   --  Render the node instance from the document.
   overriding
   procedure Render (Engine : in out Text_Renderer;
                     Doc    : in Wiki.Nodes.Document;
                     Node   : in Wiki.Nodes.Node_Type);

   --  Add a line break (<br>).
   procedure Add_Line_Break (Document : in out Text_Renderer);

   --  Add a blockquote (<blockquote>).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   procedure Add_Blockquote (Document : in out Text_Renderer;
                             Level    : in Natural);

   --  Add a list item (<li>).  Close the previous paragraph and list item if any.
   --  The list item will be closed at the next list item, next paragraph or next header.
   procedure Add_List_Item (Document : in out Text_Renderer;
                            Level    : in Positive;
                            Ordered  : in Boolean);

   --  Add a link.
   procedure Add_Link (Document : in out Text_Renderer;
                       Title    : in Wiki.Strings.WString;
                       Attr     : in Wiki.Attributes.Attribute_List_Type);

   --  Add an image.
   procedure Add_Image (Document    : in out Text_Renderer;
                        Link        : in Unbounded_Wide_Wide_String;
                        Alt         : in Unbounded_Wide_Wide_String;
                        Position    : in Unbounded_Wide_Wide_String;
                        Description : in Unbounded_Wide_Wide_String);

   --  Add a text block that is pre-formatted.
   procedure Add_Preformatted (Document : in out Text_Renderer;
                               Text     : in Unbounded_Wide_Wide_String;
                               Format   : in Unbounded_Wide_Wide_String);

   --  Finish the document after complete wiki text has been parsed.
   overriding
   procedure Finish (Document : in out Text_Renderer);

private

   --  Emit a new line.
   procedure New_Line (Document : in out Text_Renderer);

   procedure Close_Paragraph (Document : in out Text_Renderer);
   procedure Open_Paragraph (Document : in out Text_Renderer);

   type Text_Renderer is new Wiki.Render.Renderer with record
      Output         : Streams.Output_Stream_Access := null;
      Format         : Wiki.Documents.Format_Map := (others => False);
      Has_Paragraph  : Boolean := False;
      Need_Paragraph : Boolean := False;
      Empty_Line     : Boolean := True;
      Indent_Level   : Natural := 0;
   end record;

end Wiki.Render.Text;

-----------------------------------------------------------------------
--  wiki-render-text -- Wiki Text renderer
--  Copyright (C) 2011, 2012, 2013, 2015, 2016 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 Wiki.Attributes;
with Wiki.Streams;
with Wiki.Strings;

--  == Text Renderer ==
--  The <tt>Text_Renderer</tt> allows to render a wiki document into a text content.
--  The formatting rules are ignored except for the paragraphs and sections.
package Wiki.Render.Text is

   --  ------------------------------
   --  Wiki to Text renderer
   --  ------------------------------
   type Text_Renderer is new Wiki.Render.Renderer with private;

   --  Set the output stream.
   procedure Set_Output_Stream (Engine : in out Text_Renderer;
                                Stream : in Streams.Output_Stream_Access);

   --  Render the node instance from the document.
   overriding
   procedure Render (Engine : in out Text_Renderer;
                     Doc    : in Wiki.Nodes.Document;
                     Node   : in Wiki.Nodes.Node_Type);

   --  Add a line break (<br>).
   procedure Add_Line_Break (Document : in out Text_Renderer);

   --  Add a blockquote (<blockquote>).  The level indicates the blockquote nested level.
   --  The blockquote must be closed at the next header.
   procedure Add_Blockquote (Document : in out Text_Renderer;
                             Level    : in Natural);

   --  Add a list item (<li>).  Close the previous paragraph and list item if any.
   --  The list item will be closed at the next list item, next paragraph or next header.
   procedure Add_List_Item (Document : in out Text_Renderer;
                            Level    : in Positive;
                            Ordered  : in Boolean);

   --  Add a link.
   procedure Add_Link (Document : in out Text_Renderer;
                       Title    : in Wiki.Strings.WString;
                       Attr     : in Wiki.Attributes.Attribute_List_Type);

   --  Add an image.
   procedure Add_Image (Document    : in out Text_Renderer;
                        Link        : in Unbounded_Wide_Wide_String;
                        Alt         : in Unbounded_Wide_Wide_String;
                        Position    : in Unbounded_Wide_Wide_String;
                        Description : in Unbounded_Wide_Wide_String);

   --  Add a text block that is pre-formatted.
   procedure Add_Preformatted (Document : in out Text_Renderer;
                               Text     : in Unbounded_Wide_Wide_String;
                               Format   : in Unbounded_Wide_Wide_String);

   --  Finish the document after complete wiki text has been parsed.
   overriding
   procedure Finish (Document : in out Text_Renderer);

private

   --  Emit a new line.
   procedure New_Line (Document : in out Text_Renderer);

   procedure Close_Paragraph (Document : in out Text_Renderer);
   procedure Open_Paragraph (Document : in out Text_Renderer);

   type Text_Renderer is new Wiki.Render.Renderer with record
      Output         : Streams.Output_Stream_Access := null;
      Format         : Wiki.Format_Map := (others => False);
      Has_Paragraph  : Boolean := False;
      Need_Paragraph : Boolean := False;
      Empty_Line     : Boolean := True;
      Indent_Level   : Natural := 0;
   end record;

end Wiki.Render.Text;

Use Wiki.Format_Map type

Use Wiki.Format_Map type