----------------------------------------------------------------------- -- gen-model-xmi -- UML-XMI model -- Copyright (C) 2012, 2013, 2018, 2021, 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 Ada.Containers.Hashed_Maps; with Ada.Strings.Unbounded.Hash; with Ada.Containers.Vectors; with Util.Strings.Sets; package Gen.Model.XMI is type Element_Type is (XMI_UNKNOWN, XMI_PACKAGE, XMI_CLASS, XMI_GENERALIZATION, XMI_ASSOCIATION, XMI_ASSOCIATION_END, XMI_ATTRIBUTE, XMI_OPERATION, XMI_PARAMETER, XMI_ENUMERATION, XMI_ENUMERATION_LITERAL, XMI_TAGGED_VALUE, XMI_TAG_DEFINITION, XMI_DATA_TYPE, XMI_STEREOTYPE, XMI_COMMENT); -- Defines the visibility of an element (a package, class, attribute, operation). type Visibility_Type is (VISIBILITY_PUBLIC, VISIBILITY_PACKAGE, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE); -- Defines whether an attribute or association changes. type Changeability_Type is (CHANGEABILITY_INSERT, CHANGEABILITY_CHANGEABLE, CHANGEABILITY_FROZEN); type Parameter_Type is (PARAM_IN, PARAM_OUT, PARAM_INOUT, PARAM_RETURN); type Model_Element is tagged; type Tagged_Value_Element is tagged; type Tag_Definition_Element is tagged; type Model_Element_Access is access all Model_Element'Class; type Tagged_Value_Element_Access is access all Tagged_Value_Element'Class; type Tag_Definition_Element_Access is access all Tag_Definition_Element'Class; -- Define a list of model elements. package Model_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Model_Element_Access); subtype Model_Vector is Model_Vectors.Vector; subtype Model_Cursor is Model_Vectors.Cursor; -- Define a map to search an element from its XMI ID. package Model_Map is new Ada.Containers.Hashed_Maps (Key_Type => UString, Element_Type => Model_Element_Access, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => "="); subtype Model_Map_Cursor is Model_Map.Cursor; type Model_Map_Access is access all Model_Map.Map; -- Returns true if the table cursor contains a valid table function Has_Element (Position : in Model_Map_Cursor) return Boolean renames Model_Map.Has_Element; -- Returns the table definition. function Element (Position : in Model_Map_Cursor) return Model_Element_Access renames Model_Map.Element; -- Move the iterator to the next table definition. procedure Next (Position : in out Model_Map_Cursor) renames Model_Map.Next; -- Iterate on the model element of the type On and execute the Process -- procedure. procedure Iterate (Model : in Model_Map.Map; On : in Element_Type; Process : not null access procedure (Id : in UString; Node : in Model_Element_Access)); -- Generic procedure to iterate over the XMI elements of a vector -- and having the entity name name. generic type T (<>) is limited private; procedure Iterate_Elements (Closure : in out T; List : in Model_Vector; Process : not null access procedure (Closure : in out T; Node : in Model_Element_Access)); -- Map of UML models indexed on the model name. package UML_Model_Map is new Ada.Containers.Hashed_Maps (Key_Type => UString, Element_Type => Model_Map.Map, Hash => Ada.Strings.Unbounded.Hash, Equivalent_Keys => "=", "=" => Model_Map."="); subtype UML_Model is UML_Model_Map.Map; type UML_Model_Access is access all UML_Model; type Search_Type is (BY_NAME, BY_ID); -- Find the model element with the given XMI id. -- Returns null if the model element is not found. function Find (Model : in Model_Map.Map; Key : in String; Mode : in Search_Type := BY_ID) return Model_Element_Access; -- Find the model element within all loaded UML models. -- Returns null if the model element is not found. function Find (Model : in UML_Model; Current : in Model_Map.Map; Id : in UString) return Model_Element_Access; -- Dump the XMI model elements. procedure Dump (Map : in Model_Map.Map); -- Reconcile all the UML model elements by resolving all the references to UML elements. procedure Reconcile (Model : in out UML_Model; Debug : in Boolean := False); -- ------------------------------ -- Model Element -- ------------------------------ type Model_Element (Model : Model_Map_Access) is abstract new Definition with record -- Element XMI id. XMI_Id : UString; -- List of tagged values for the element. Tagged_Values : Model_Vector; -- Elements contained. Elements : Model_Vector; -- Stereotypes associated with the element. Stereotypes : Model_Vector; -- The parent model element; Parent : Model_Element_Access; end record; -- Get the element type. function Get_Type (Node : in Model_Element) return Element_Type is abstract; -- Reconcile the element by resolving the references to other elements in the model. procedure Reconcile (Node : in out Model_Element; Model : in UML_Model); -- Find the element with the given name. If the name is a qualified name, navigate -- down the package/class to find the appropriate element. -- Returns null if the element was not found. function Find (Node : in Model_Element; Name : in String) return Model_Element_Access; -- Set the model name. procedure Set_Name (Node : in out Model_Element; Value : in UBO.Object); -- Set the model XMI unique id. procedure Set_XMI_Id (Node : in out Model_Element; Value : in UBO.Object); -- Validate the node definition as much as we can before the reconcile phase. -- If an error is detected, return a message. Returns an empty string if everything is ok. function Get_Error_Message (Node : in Model_Element) return String; -- Find the tag value element with the given name. -- Returns null if there is no such tag. function Find_Tag_Value (Node : in Model_Element; Name : in String) return Tagged_Value_Element_Access; -- Find the tag value associated with the given tag definition. -- Returns the tag value if it was found, otherwise returns the default function Find_Tag_Value (Node : in Model_Element; Definition : in Tag_Definition_Element_Access; Default : in String := "") return String; -- Get the documentation and comment associated with the model element. -- Returns the empty string if there is no comment. function Get_Comment (Node : in Model_Element) return String; -- Get the full qualified name for the element. function Get_Qualified_Name (Node : in Model_Element) return String; -- Dump the node to get some debugging description about it. procedure Dump (Node : in Model_Element); -- Find from the model file identified by Name, the model element with the -- identifier or name represented by Key. -- Returns null if the model element is not found. generic type Element_Type is new Model_Element with private; type Element_Type_Access is access all Element_Type'Class; function Find_Element (Model : in UML_Model; Name : in String; Key : in String; Mode : in Search_Type := BY_ID) return Element_Type_Access; -- ------------------------------ -- Data type -- ------------------------------ type Ref_Type_Element is new Model_Element with record Ref_Id : UString; Ref : Model_Element_Access; end record; type Ref_Type_Element_Access is access all Ref_Type_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Ref_Type_Element) return Element_Type; -- Reconcile the element by resolving the references to other elements in the model. overriding procedure Reconcile (Node : in out Ref_Type_Element; Model : in UML_Model); -- Set the reference id and collect in the profiles set the UML profiles that must -- be loaded to get the reference. procedure Set_Reference_Id (Node : in out Ref_Type_Element; Ref : in String; Profiles : in out Util.Strings.Sets.Set); -- ------------------------------ -- Data type -- ------------------------------ type Data_Type_Element is new Model_Element with record Parent_Type : Ref_Type_Element_Access; end record; type Data_Type_Element_Access is access all Data_Type_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Data_Type_Element) return Element_Type; -- ------------------------------ -- Enum -- ------------------------------ type Enum_Element is new Data_Type_Element with null record; type Enum_Element_Access is access all Enum_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Enum_Element) return Element_Type; -- Validate the node definition as much as we can before the reconcile phase. -- An enum must not be empty, it must have at least one literal. -- If an error is detected, return a message. Returns an empty string if everything is ok. overriding function Get_Error_Message (Node : in Enum_Element) return String; -- ------------------------------ -- Literal -- ------------------------------ -- The literal describes a possible value for an enum. type Literal_Element is new Model_Element with null record; type Literal_Element_Access is access all Literal_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Literal_Element) return Element_Type; -- Create an enum literal and add it to the enum. procedure Add_Literal (Node : in out Enum_Element; Id : in UBO.Object; Name : in UBO.Object; Literal : out Literal_Element_Access); -- ------------------------------ -- Stereotype -- ------------------------------ type Stereotype_Element is new Model_Element with null record; type Stereotype_Element_Access is access all Stereotype_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Stereotype_Element) return Element_Type; -- Returns True if the model element has the stereotype with the given name. function Has_Stereotype (Node : in Model_Element'Class; Stereotype : in Stereotype_Element_Access) return Boolean; -- ------------------------------ -- Comment -- ------------------------------ type Comment_Element is new Model_Element with record Text : UString; Ref_Id : UString; end record; type Comment_Element_Access is access all Comment_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Comment_Element) return Element_Type; -- ------------------------------ -- An operation -- ------------------------------ type Operation_Element is new Model_Element with record Visibility : Visibility_Type := VISIBILITY_PUBLIC; end record; type Operation_Element_Access is access all Operation_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Operation_Element) return Element_Type; -- ------------------------------ -- An attribute -- ------------------------------ type Attribute_Element is new Ref_Type_Element with record Data_Type : Data_Type_Element_Access; Visibility : Visibility_Type := VISIBILITY_PUBLIC; Changeability : Changeability_Type := CHANGEABILITY_CHANGEABLE; Initial_Value : UBO.Object; Multiplicity_Lower : Integer := 0; Multiplicity_Upper : Integer := 1; end record; type Attribute_Element_Access is access all Attribute_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Attribute_Element) return Element_Type; -- Reconcile the element by resolving the references to other elements in the model. overriding procedure Reconcile (Node : in out Attribute_Element; Model : in UML_Model); -- ------------------------------ -- A parameter -- ------------------------------ type Parameter_Element is new Attribute_Element with record Kind : Parameter_Type := PARAM_IN; end record; type Parameter_Element_Access is access all Parameter_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Parameter_Element) return Element_Type; -- ------------------------------ -- An association end -- ------------------------------ type Association_End_Element is new Ref_Type_Element with record Visibility : Visibility_Type := VISIBILITY_PUBLIC; Multiplicity_Lower : Integer := 0; Multiplicity_Upper : Integer := 0; Target_Element : Model_Element_Access; Source_Element : Model_Element_Access; Navigable : Boolean := True; end record; type Association_End_Element_Access is access all Association_End_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Association_End_Element) return Element_Type; -- Get the documentation and comment associated with the model element. -- Integrates the comment from the association itself as well as this association end. -- Returns the empty string if there is no comment. overriding function Get_Comment (Node : in Association_End_Element) return String; -- Reconcile the element by resolving the references to other elements in the model. overriding procedure Reconcile (Node : in out Association_End_Element; Model : in UML_Model); -- Make the association between the two ends. procedure Make_Association (From : in out Association_End_Element; To : in out Association_End_Element'Class; Model : in UML_Model); -- ------------------------------ -- An association -- ------------------------------ type Association_Element is new Model_Element with record Visibility : Visibility_Type := VISIBILITY_PUBLIC; Connections : Model_Vector; end record; type Association_Element_Access is access all Association_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Association_Element) return Element_Type; -- Validate the node definition as much as we can before the reconcile phase. -- An association must contain two ends and a name is necessary on the navigable ends. -- If an error is detected, return a message. Returns an empty string if everything is ok. overriding function Get_Error_Message (Node : in Association_Element) return String; -- Reconcile the association between classes in the package. Find the association -- ends and add the necessary links to the corresponding class elements. overriding procedure Reconcile (Node : in out Association_Element; Model : in UML_Model); -- ------------------------------ -- An association -- ------------------------------ type Generalization_Element is new Ref_Type_Element with record Child_Class : Model_Element_Access; Child_Id : UString; end record; type Generalization_Element_Access is access all Generalization_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Generalization_Element) return Element_Type; -- Reconcile the association between classes in the package. Find the association -- ends and add the necessary links to the corresponding class elements. overriding procedure Reconcile (Node : in out Generalization_Element; Model : in UML_Model); -- ------------------------------ -- Tag Definition -- ------------------------------ TAG_DOCUMENTATION : constant String := "documentation"; TAG_AUTHOR : constant String := "author"; type Tag_Definition_Element is new Model_Element with record Multiplicity_Lower : Natural := 0; Multiplicity_Upper : Natural := 0; end record; -- Get the element type. overriding function Get_Type (Node : in Tag_Definition_Element) return Element_Type; -- ------------------------------ -- Tagged value -- ------------------------------ type Tagged_Value_Element is new Ref_Type_Element with record Value : UString; Value_Type : UString; Tag_Def : Tag_Definition_Element_Access; end record; -- Get the element type. overriding function Get_Type (Node : in Tagged_Value_Element) return Element_Type; -- Reconcile the element by resolving the references to other elements in the model. overriding procedure Reconcile (Node : in out Tagged_Value_Element; Model : in UML_Model); -- ------------------------------ -- A class -- ------------------------------ type Class_Element is new Data_Type_Element with record Operations : Model_Vector; Attributes : Model_Vector; Associations : Model_Vector; Visibility : Visibility_Type := VISIBILITY_PUBLIC; Parent_Class : Ref_Type_Element_Access; end record; type Class_Element_Access is access all Class_Element'Class; -- Get the element type. overriding function Get_Type (Node : in Class_Element) return Element_Type; -- Reconcile the element by resolving the references to other elements in the model. overriding procedure Reconcile (Node : in out Class_Element; Model : in UML_Model); -- ------------------------------ -- A package -- ------------------------------ type Package_Element is tagged; type Package_Element_Access is access all Package_Element'Class; type Package_Element is new Model_Element with record Classes : Model_Vector; Enums : Model_Vector; Associations : Model_Vector; Types : Model_Vector; Is_Profile : Boolean := False; end record; -- Get the element type. overriding function Get_Type (Node : in Package_Element) return Element_Type; end Gen.Model.XMI;