Book a Demo

Author Topic: Creating an Interface and a Class from a Class in a Transformation  (Read 6032 times)

Jeff Hegedus

  • EA Novice
  • *
  • Posts: 15
  • Karma: +0/-0
    • View Profile
I've been working on a transformation for C# but the model that I need to transform uses multiple inheritance.  C# does not support multiple class inheritance, though it does support implementation of multiple interfaces.  So in my transform, I'm checking if the class is inherited by a class that uses multiple inheritance and if it is, I'm trying to create an interface and a class from the original class and change all of the original generalizations to point to the newly created interface.

The code in the intermediate file looks right to me and everything works except the associations to the interface created by the transformation.  I've pasted the text from the intermediate file specific to the associations that are not working, the transformation code and a link to the full text of the intermediate file below.  There is an EXEC_ADD_IN call to determine if the class is inherited by a class that uses multiple inheritance in the transformation and I have not posted the addin code but I have tested the function used and verified that it operates as expected.

Does anyone see what could be causing the problem?  Any help will be greatly appreciated.

---------------------------- Associations from the Intermediate File -------------------------------------
Code: [Select]
Association
{
  notes=""
  alias=""
  name="A_upperValue_owningUpper"
  stereotype=""
  direction="Source -> Destination"
  XRef{namespace="C#" name="Connector" source="{8C04F9C8-612A-43d9-9312-EC0BB21D899D}"}
  Source
  {
  XRef{namespace="C#" name="Class" source="{4AAEB96F-92DE-4076-BCE6-1A2E7AEE6C17}"}
    access="Private"
  notes=""
  qualifier=""
  ordered="0"
  scope=""
  multiplicity="0"
  role="owningUpper"
  alias=""
  containment=""
  stereotype=""
  membertype=""
  allowduplicates=""
  navigability="Non-Navigable"
  changeable=""
  constraint=""
  aggregation="2"
  }
  Target
  {
  XRef{namespace="C#" name="Class" source="{DD7BB394-4F3E-4dd5-98B7-34924F8FB403}"}
    access="Private"
  notes="The specification of the upper bound for this multiplicity."
  qualifier=""
  ordered="0"
  scope=""
  multiplicity="0"
  alias=""
  containment=""
  stereotype=""
  membertype=""
  allowduplicates=""
  navigability="Navigable"
  changeable=""
  constraint=""
  aggregation="0"
  role="upperValue"
  }
}
Association
{
  notes=""
  alias=""
  name="A_lowerValue_owningLower"
  stereotype=""
  direction="Source -> Destination"
  XRef{namespace="C#" name="Connector" source="{322D7D08-5A0A-4054-9779-5923BE8090F1}"}
  Source
  {
  XRef{namespace="C#" name="Class" source="{4AAEB96F-92DE-4076-BCE6-1A2E7AEE6C17}"}
    access="Private"
  notes=""
  qualifier=""
  ordered="0"
  scope=""
  multiplicity="0"
  role="owningLower"
  alias=""
  containment=""
  stereotype=""
  membertype=""
  allowduplicates=""
  navigability="Non-Navigable"
  changeable=""
  constraint=""
  aggregation="2"
  }
  Target
  {
  XRef{namespace="C#" name="Class" source="{DD7BB394-4F3E-4dd5-98B7-34924F8FB403}"}
    access="Private"
  notes="The specification of the lower bound for this multiplicity."
  qualifier=""
  ordered="0"
  scope=""
  multiplicity="0"
  alias=""
  containment=""
  stereotype=""
  membertype=""
  allowduplicates=""
  navigability="Navigable"
  changeable=""
  constraint=""
  aggregation="0"
  role="lowerValue"
  }
}
---------------------------- Associations from the Intermediate File -------------------------------------



----------------------------------------- Class Template ---------------------------------------------------
Code: [Select]
$templateName = "Class__EIIW_Class"
%if elemType != "Class" and elemType != "Interface" and elemType != "Enumeration"%
%endTemplate%

$isMultiplyInherited = %EXEC_ADD_IN("EIIWEAAddin", "IsMultiplyInherited", classGUID)%
%if $isMultiplyInherited == "true"%
$interfaceName="I"+%className%

Interface
{
  %TRANSFORM_REFERENCE("Interface", classGUID)%
  %TRANSFORM_CURRENT("language", "name")%
  name=%qt%$interfaceName%qt%
  language="C#"
%list="ClassBase" @separator="\n" @indent="  "%
%list="ClassInterface" @separator="\n" @indent="  "%
%list="InnerClass" @separator="\n" @indent="  "%
%list="Attribute__Property" @separator="\n" @indent="  " attScope=="Public"%
%list="Operation" @separator="\n" @indent="  "%
}
%list="Connector__EIIW_InterfaceConnectorsFromClass" @separator="\n"%

%elemType%
{
  %TRANSFORM_REFERENCE("Class")%
  %TRANSFORM_CURRENT("language")%
  language="C#"
%list="ClassBase" @separator="\n" @indent="  "%
%list="ClassInterface" @separator="\n" @indent="  "%
%list="InnerClass" @separator="\n" @indent="  "%
%if elemType!="Interface"%
%list="Attribute" @separator="\n" @indent="  "%
%endIf%
%list="Attribute__Property" @separator="\n" @indent="  " attScope=="Public"%
%list="Operation" @separator="\n" @indent="  "%
}
%list="Connector__EIIW_Association" @separator="\n"%

Generalization
{
%TRANSFORM_REFERENCE("Connector", classGUID)%
Source
{
%TRANSFORM_REFERENCE("Class",classGUID)%
  access=%qt%Public%qt%
  notes=%qt%Generalization to transformation created interface.%qt%
}
Target
{
%TRANSFORM_REFERENCE("Interface",classGUID)%
  access=%qt%Public%qt%
}
}

%else%

%elemType%
{
  %TRANSFORM_REFERENCE("Class")%
  %TRANSFORM_CURRENT("language")%
  language="C#"
%list="ClassBase" @separator="\n" @indent="  "%
%list="ClassInterface" @separator="\n" @indent="  "%
%list="InnerClass" @separator="\n" @indent="  "%
%if elemType!="Interface"%
%list="Attribute" @separator="\n" @indent="  "%
%endIf%
%list="Attribute__Property" @separator="\n" @indent="  " attScope=="Public"%
%list="Operation" @separator="\n" @indent="  "%
}
%list="Connector__EIIW_Association" @separator="\n"%
%endIf%
----------------------------------------- Class Template ---------------------------------------------------

-------------------------------------- Connector Template -------------------------------------------------
Code: [Select]
$templateName = "Connector"
%connectorType%
%PI="\n  "%
{
%TRANSFORM_CURRENT()%
%TRANSFORM_REFERENCE("Connector",connectorGUID)%
%if connectorIsAssociationClass=="T"%
AssociationClass
{
%TRANSFORM_REFERENCE("Class",connectorAssociationClassElemGUID)%
}
%endIf%
Source
{
$debugMessage=%classGUID%
$debugMessage = "classGUID == " + $debugMessage
%DebugMessage($templateName, $debugMessage)%
%if connectorSourceElemGUID == classGUID%
$debugMessage = "connectorSourceElemGUID == classGUID"
%DebugMessage($templateName, $debugMessage)%
%TRANSFORM_REFERENCE("Interface",classGUID)%
%else%
$debugMessage = "connectorSourceElemGUID != classGUID"
%DebugMessage($templateName, $debugMessage)%
%TRANSFORM_REFERENCE("Class",connectorSourceElemGUID)%
%endIf%
  access=%qt%%connectorSourceAccess == "Public" ? "Private" : value%%qt%
%TRANSFORM_CURRENT("Source","access")%
}
Target
{
%if connectorDestElemGUID == classGUID%
$debugMessage = "connectorDestElemGUID == classGUID"
%DebugMessage($templateName, $debugMessage)%
%TRANSFORM_REFERENCE("Interface",classGUID)%
%else%
$debugMessage = "connectorDestElemGUID != classGUID"
%DebugMessage($templateName, $debugMessage)%
%TRANSFORM_REFERENCE("Class",connectorDestElemGUID)%
%endIf%
  access=%qt%%connectorDestAccess == "Public" ? "Private" : value%%qt%
%TRANSFORM_CURRENT("Target","access", "role")%
$role=%connectorDestRole == "object" ? "objectAttr" : value%
$role=%EIIW_ConvertName($role)%
role=%qt%$role%qt%
%PI="\n"%
}
}
-------------------------------------- Connector Template -------------------------------------------------

https://onedrive.live.com/prev?id=1737A31617426660%2159459&cid=1737A31617426660&parId=1737A31617426660%21134&v=TextFileEditor

smither

  • EA Novice
  • *
  • Posts: 13
  • Karma: +0/-0
    • View Profile
Re: Creating an Interface and a Class from a Class in a Transformation
« Reply #1 on: January 22, 2016, 10:10:29 pm »
Hi Jeff, tricky stuff indeed...

Your problem is that you are creating two associations with the same reference, causing the second one to overwrite the first when the intermediate file is processed.  The Association specified by the block starting on line 446 of your intermediate file has an XRef:

 XRef{namespace="C#" name="Connector" source="{8C04F9C8-612A-43d9-9312-EC0BB21D899D}"}

as does the Association starting on line 1043.  The first association is between the interface and some other class, while the second one is between the class and that other class.  The second one wins.

I'm not going to second guess the solution, but either you need to not create the second association, or give the first one a different XRef 'name'...

Regards
Eric