Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: Hurra on April 21, 2020, 01:48:36 am
-
Hello!
Given this scenario:
(https://i.imgur.com/sJk9xP2.png)
The activities have internal information flows as well. Act2 recieves Block1 and 2, but internally they go to different places. Same thing for Act 1, it sends Block1 and 2, but it gets to the border of Act1 from different places (internally).
I wanted to create a script to make sure all incoming conveyed objects are equal to all outgoing conveyed objects.
ez-pz I thought.
I just make a script which starts on an element, looks for embedded elements (ports and pins), look for all connectors, save as two arrays, incoming and outgoing connectors, find the conveyed objects, and compare.
Well, I have a bit of a problem.
The connector above is just not one connector. It is an Object Flow and an Information Flow? When I tried to find the conveyed objects of the Object Flow I find nothing. But on the Information Flow I do.
However, the Object Flow is, visually, an aggregation of all Information Flows. But in reality, no objects are conveyed?
I wanted to use the Object Flow, because there are less Object Flow connectors.
I mean, I will script this so I guess there is no problem to use A LOT more Information Flow connectors instead of a few Object Flow connectors. But I wanted to understand this before I make any final decisions of how I should approach this.
Can someone explain the relationship between Information Flow and Object Flow, or guide me in the correct direction?
Hopefully you understand what I'm asking.
(https://i.imgur.com/idmGA1K.png)
Thank you for your time and expertise!
Robert
-
The way I would model it would not use information flows. Give each action two action pins, Pin1:Block1 and Pin2:Block2 and use two object flows, one connecting Pin1 to Pin1 and the other connecting Pin2 to Pin2.
-
This is how I do in in my framework code: https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs (https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs)
public HashSet<UML.Classes.Kernel.Classifier> conveyed
{
get
{
if (_conveyed == null)
{
string getXrefDescription = @"select x.Description from t_xref x
where x.Name = 'MOFProps'
and x.Behavior = 'conveyed'
and x.client = '" + this.guid + "'";
//xrefdescription contains the GUID's of the conveyed elements comma separated
var xrefDescription = this.EAModel.SQLQuery(getXrefDescription).SelectSingleNode(this.EAModel.formatXPath("//Description"));
if (xrefDescription != null)
{
foreach (string conveyedGUID in xrefDescription.InnerText.Split(','))
{
var conveyedElement = this.EAModel.getElementWrapperByGUID(conveyedGUID) as UML.Classes.Kernel.Classifier;
if (conveyedElement != null)
{
//initialize if needed
if (_conveyed == null)
{
_conveyed = new HashSet<UML.Classes.Kernel.Classifier>();
}
//add the element
_conveyed.Add(conveyedElement);
}
}
}
}
//nothing found, return empty list.
if (_conveyed == null)
{
_conveyed = new HashSet<UML.Classes.Kernel.Classifier>();
}
return _conveyed;
}
set
{
throw new NotImplementedException();
}
}
Geert
-
The way I would model it would not use information flows. Give each action two action pins, Pin1:Block1 and Pin2:Block2 and use two object flows, one connecting Pin1 to Pin1 and the other connecting Pin2 to Pin2.
Well, the information flows 'just appears'. I create an object flow. Then I add the conveyed objects by right clicking on the connector, advanced > information flows realized, and select the object. This creates the information flow relationship.
Are you saying I can convey an object another way..?
Regarding Pin1 -> Pin1, and Pin2 -> Pin2, we have modeled it with this approach;
Each activity has one pin to recieve information, and one pin to send information. Like input and output pins.
This is how I do in in my framework code: https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs (https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs)
...
Geert
Thanks Geert, although - as for now - I have no problem with code/SQL. But handy to have your approach available, thanks!
-
This is how I do in in my framework code: https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs (https://github.com/GeertBellekens/Enterprise-Architect-Add-in-Framework/blob/cb75f9a1e84ccfdcc348a79c90da5e148f92f97c/EAAddinFramework/EAWrappers/InformationFlow.cs)
public HashSet<UML.Classes.Kernel.Classifier> conveyed
{
get
{
if (_conveyed == null)
{
string getXrefDescription = @"select x.Description from t_xref x
where x.Name = 'MOFProps'
and x.Behavior = 'conveyed'
and x.client = '" + this.guid + "'";
//xrefdescription contains the GUID's of the conveyed elements comma separated
var xrefDescription = this.EAModel.SQLQuery(getXrefDescription).SelectSingleNode(this.EAModel.formatXPath("//Description"));
if (xrefDescription != null)
{
foreach (string conveyedGUID in xrefDescription.InnerText.Split(','))
{
var conveyedElement = this.EAModel.getElementWrapperByGUID(conveyedGUID) as UML.Classes.Kernel.Classifier;
if (conveyedElement != null)
{
//initialize if needed
if (_conveyed == null)
{
_conveyed = new HashSet<UML.Classes.Kernel.Classifier>();
}
//add the element
_conveyed.Add(conveyedElement);
}
}
}
}
//nothing found, return empty list.
if (_conveyed == null)
{
_conveyed = new HashSet<UML.Classes.Kernel.Classifier>();
}
return _conveyed;
}
set
{
throw new NotImplementedException();
}
}
Geert
Hi!
I just now realized what you did there...
Thank you, will give it a try!
-
Hi Robert,
I agree with KP that information flows is not what you would typically see within an activity diagram. I believe that by using information flows between InputPins and OutputPins you are actually violating the UML spec. (You could use them between ActivityNodes but this is also not a very common usage.) Instead you should use object flows as KP suggests.
However, in an ibd, you would typically use item flows (the SysML variant of information flows) that conveys items between properties. In this case Sparx has adopted a somewhat problematic approach with respect to their underlying implementation. The information about conveyed items are stored within the xref table which can only hold up to 7 conveyed items per information flow. If I remember correctly it is alos not possible to realise more than 7 item flows to the same connector because of the length of the Decription field in the xref table.
I attach an example SQL fragment that I use to extract this kind of information. Yes, it is long, but is working fine if you can modify it according to your specific situation. It will extract any information that is conveyed within a block (id 28246). It may be the case that I have used some specific MySQL/MariaDB statement.
SELECT
Neighbour_Name, Connector_Name, Connector_ID, Flow_Id,
[Neighbour_Type.Hyperlink],
Consumer_Name AS SIF,ifnull(CONCAT(ConsumerType_guid,ConsumerType_Name),'') AS "ConsumerPort_Type.Hyperlink",
TRIM(TRAILING ', ' FROM CONCAT(GROUP_CONCAT(DISTINCT Recieved_Name SEPARATOR ', '),', ',ifnull(GROUP_CONCAT(Recieved_Items SEPARATOR ', '),''))) AS "SIF_mottar",
TRIM(TRAILING ', ' FROM CONCAT(GROUP_CONCAT(DISTINCT Transmitted_Name SEPARATOR ', '),', ',ifnull(GROUP_CONCAT(Transmitted_Items SEPARATOR ', '),''))) AS "SIF_skickar",
Producer_Name AS IFS,ifnull(CONCAT(ProducerType_guid,ProducerType_Name),'') AS "ProducerPort_Type.Hyperlink"
FROM
(
SELECT
TRIM(LEADING ':' FROM CONCAT(ifnull(PRODUCERPP.Name,''),'::',ifnull(PRODUCERP.Name,''),'::',ifnull(PRODUCER.Name,''))) AS Neighbour_Name,
ifnull(CONCAT(PRODUCERTYPE.ea_guid,PRODUCERTYPE.Name),'') AS "Neighbour_Type.Hyperlink",
CONNECTOR.Name AS Connector_Name,
CONNECTOR.Connector_ID AS Connector_ID,
CONNECTOR.Stereotype AS Connector_Type,
FLOW.Stereotype AS Flow_Type,
FLOW.Connector_ID AS Flow_Id,
CONVEYED.Stereotype AS Conveyed_Type,
NULL AS Transmitted_Name,
NULL AS Transmitted_Items,
CONVEYED.Name AS Recieved_Name,
ITEMPROPERTY.Name AS Recieved_Items,
PRODUCER.Stereotype AS Producer_Type,
TRIM(LEADING ':' FROM CONCAT(ifnull(PRODUCERPP.Name,''),'::',ifnull(PRODUCERP.Name,''),'::',ifnull(PRODUCER.Name,''))) AS Producer_Name,
PRODUCERTYPE.ea_guid AS ProducerType_guid,PRODUCERTYPE.Name AS ProducerType_Name,
CONSUMER.Stereotype AS Consumer_Type,
TRIM(LEADING ':' FROM CONCAT(ifnull(CONSUMERPP.Name,''),'::',ifnull(CONSUMERP.Name,''),'::',ifnull(CONSUMER.Name,''))) AS Consumer_Name,
CONSUMERTYPE.ea_guid AS ConsumerType_guid,CONSUMERTYPE.Name AS ConsumerType_Name,
FLOW.SubType
FROM
(((((((((((((t_connector FLOW
LEFT JOIN
(
SELECT opid.Property, opid.ElementID, CONCAT(test.Name,":",type.Name) AS Name, test.Stereotype AS Stereotype, test.Object_Type AS Object_Type
FROM ((t_connectortag opid
INNER JOIN t_object test ON test.ea_guid = opid.VALUE)
LEFT JOIN t_object type ON type.ea_guid = test.PDATA1)
WHERE (opid.Property='itemProperty')
) ITEMPROPERTY ON FLOW.Connector_ID = ITEMPROPERTY.ElementID)
INNER JOIN t_xref XCONVEYED ON XCONVEYED.Client = FLOW.ea_guid)
LEFT JOIN t_object CONVEYED ON (CONVEYED.ea_guid in (
left(XCONVEYED.Description,38),
mid(XCONVEYED.Description,40,38),
mid(XCONVEYED.Description,79,38),
mid(XCONVEYED.Description,118,38),
mid(XCONVEYED.Description,157,38),
mid(XCONVEYED.Description,196,38),
mid(XCONVEYED.Description,235,38),
mid(XCONVEYED.Description,274,38),
mid(XCONVEYED.Description,313,38),
mid(XCONVEYED.Description,352,38))) )
INNER JOIN t_xref XABSTRACTION ON (XCONVEYED.Client in (
left(XABSTRACTION.Description,38),
mid(XABSTRACTION.Description,40,38),
mid(XABSTRACTION.Description,79,38),
mid(XABSTRACTION.Description,118,38),
mid(XABSTRACTION.Description,157,38),
mid(XABSTRACTION.Description,196,38),
mid(XABSTRACTION.Description,235,38),
mid(XABSTRACTION.Description,274,38),
mid(XABSTRACTION.Description,313,38),
mid(XABSTRACTION.Description,352,38))))
INNER JOIN t_connector CONNECTOR ON CONNECTOR.ea_guid = XABSTRACTION.Client)
INNER JOIN t_object PRODUCER ON CONNECTOR.Start_Object_ID = PRODUCER.Object_ID)
INNER JOIN t_object CONSUMER ON CONNECTOR.End_Object_ID = CONSUMER.Object_ID)
LEFT JOIN t_object PRODUCERP ON PRODUCERP.Object_ID = PRODUCER.ParentID AND PRODUCERP.Object_Type in ('Port','Part'))
LEFT JOIN t_object CONSUMERP ON CONSUMERP.Object_ID = CONSUMER.ParentID AND CONSUMERP.Object_Type in ('Port','Part'))
LEFT JOIN t_object PRODUCERPP ON PRODUCERPP.Object_ID = PRODUCERP.ParentID AND PRODUCERPP.Object_Type in ('Port','Part'))
LEFT JOIN t_object CONSUMERPP ON CONSUMERPP.Object_ID = CONSUMERP.ParentID AND CONSUMERPP.Object_Type in ('Port','Part'))
LEFT JOIN t_object PRODUCERTYPE ON PRODUCER.PDATA1 = PRODUCERTYPE.EA_guid)
LEFT JOIN t_object CONSUMERTYPE ON CONSUMER.PDATA1 = CONSUMERTYPE.EA_guid)
WHERE
CONNECTOR.Stereotype IN ('ResourceConnector','OperationalConnector')
AND FLOW.Stereotype IN ('ResourceExchange','OperationalExchange')
AND XABSTRACTION.Behavior = 'abstraction'
AND (CONSUMER.Object_ID = 28246 OR
CONSUMERP.Object_ID = 28246 OR
CONSUMERPP.Object_ID = 28246)
UNION
SELECT
TRIM(LEADING ':' FROM CONCAT(ifnull(CONSUMERPP.Name,''),'::',ifnull(CONSUMERP.Name,''),'::',ifnull(CONSUMER.Name,''))) AS Neighbour_Name,
ifnull(CONCAT(CONSUMERTYPE.ea_guid,CONSUMERTYPE.Name),'') AS "Neighbour_Type.Hyperlink",
CONNECTOR.Name AS Connector_Name,
CONNECTOR.Connector_ID AS Connector_ID,
CONNECTOR.Stereotype AS Connector_Type,
FLOW.Stereotype AS Flow_Type,
FLOW.Connector_ID AS Flow_Id,
CONVEYED.Stereotype AS Conveyed_Type,
CONVEYED.Name AS Transmitted_Name,
ITEMPROPERTY.Name AS Transmitted_Items,
NULL AS Recieved_Name,
NULL AS Recieved_Items,
PRODUCER.Stereotype AS Producer_Type,
TRIM(LEADING ':' FROM CONCAT(ifnull(PRODUCERPP.Name,''),'::',ifnull(PRODUCERP.Name,''),'::',ifnull(PRODUCER.Name,''))) AS Producer_Name,
PRODUCERTYPE.ea_guid AS ProducerType_guid,PRODUCERTYPE.Name AS ProducerType_Name,
CONSUMER.Stereotype AS Consumer_Type,
TRIM(LEADING ':' FROM CONCAT(ifnull(CONSUMERPP.Name,''),'::',ifnull(CONSUMERP.Name,''),'::',ifnull(CONSUMER.Name,''))) AS Consumer_Name,
CONSUMERTYPE.ea_guid AS ConsumerType_guid,CONSUMERTYPE.Name AS ConsumerType_Name,
FLOW.SubType
FROM
(((((((((((((t_connector FLOW
LEFT JOIN
(
SELECT opid.Property, opid.ElementID, CONCAT(test.Name,":",type.Name) AS Name, test.Stereotype AS Stereotype, test.Object_Type AS Object_Type
FROM ((t_connectortag opid
INNER JOIN t_object test ON test.ea_guid = opid.VALUE)
LEFT JOIN t_object type ON type.ea_guid = test.PDATA1)
WHERE (opid.Property='itemProperty')
) ITEMPROPERTY ON FLOW.Connector_ID = ITEMPROPERTY.ElementID)
INNER JOIN t_xref XCONVEYED ON XCONVEYED.Client = FLOW.ea_guid)
LEFT JOIN t_object CONVEYED ON (CONVEYED.ea_guid in (
left(XCONVEYED.Description,38),
mid(XCONVEYED.Description,40,38),
mid(XCONVEYED.Description,79,38),
mid(XCONVEYED.Description,118,38),
mid(XCONVEYED.Description,157,38),
mid(XCONVEYED.Description,196,38),
mid(XCONVEYED.Description,235,38),
mid(XCONVEYED.Description,274,38),
mid(XCONVEYED.Description,313,38),
mid(XCONVEYED.Description,352,38))) )
INNER JOIN t_xref XABSTRACTION ON (XCONVEYED.Client in (
left(XABSTRACTION.Description,38),
mid(XABSTRACTION.Description,40,38),
mid(XABSTRACTION.Description,79,38),
mid(XABSTRACTION.Description,118,38),
mid(XABSTRACTION.Description,157,38),
mid(XABSTRACTION.Description,196,38),
mid(XABSTRACTION.Description,235,38),
mid(XABSTRACTION.Description,274,38),
mid(XABSTRACTION.Description,313,38),
mid(XABSTRACTION.Description,352,38))))
INNER JOIN t_connector CONNECTOR ON CONNECTOR.ea_guid = XABSTRACTION.Client)
INNER JOIN t_object PRODUCER ON CONNECTOR.Start_Object_ID = PRODUCER.Object_ID)
INNER JOIN t_object CONSUMER ON CONNECTOR.End_Object_ID = CONSUMER.Object_ID)
LEFT JOIN t_object PRODUCERP ON PRODUCERP.Object_ID = PRODUCER.ParentID AND PRODUCERP.Object_Type in ('Port','Part'))
LEFT JOIN t_object CONSUMERP ON CONSUMERP.Object_ID = CONSUMER.ParentID AND CONSUMERP.Object_Type in ('Port','Part'))
LEFT JOIN t_object PRODUCERPP ON PRODUCERPP.Object_ID = PRODUCERP.ParentID AND PRODUCERPP.Object_Type in ('Port','Part'))
LEFT JOIN t_object CONSUMERPP ON CONSUMERPP.Object_ID = CONSUMERP.ParentID AND CONSUMERPP.Object_Type in ('Port','Part'))
LEFT JOIN t_object PRODUCERTYPE ON PRODUCER.PDATA1 = PRODUCERTYPE.EA_guid)
LEFT JOIN t_object CONSUMERTYPE ON CONSUMER.PDATA1 = CONSUMERTYPE.EA_guid)
WHERE
CONNECTOR.Stereotype IN ('ResourceConnector','OperationalConnector')
AND FLOW.Stereotype IN ('ResourceExchange','OperationalExchange')
AND XABSTRACTION.Behavior = 'abstraction'
AND (PRODUCER.Object_ID = 28246 OR
PRODUCERP.Object_ID = 28246 OR
PRODUCERPP.Object_ID = 28246)
) DerivedTable
GROUP BY Connector_ID;
//Hans