Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Hurra

Pages: [1] 2 3 ... 13
1
Hello!

I have defined a custom stereotype which is a generalization of SysML1.4::block and metaclass Class.

I have defined a custom relationship with metaclass Aggregation (I don't see any stereotype on SysML relationships part/shared association).

When I create two of these stereotypes and a connector between them, it works. But I don't get any property/type object as child in the 'whole'.

I've tried to create a generalization on my custom diagram: SysML::Block Definition, but didn't do anything. The SysML diagrams doesn't seem to have a stereotype assigned to them?

How do I change my MDG to create part/properties object when adding a connector like composition/aggregation, like in the SysML MDG?

It was a long time ago since I played around creating an MDG 😇

Thanks!

Note: my stereotype have Instance Behavior Mode: Property

2
Automation Interface, Add-Ins and Tools / Re: MDG Office Archimate import
« on: November 16, 2023, 09:03:16 pm »
As long as you have created a diagram with correct type I think it works.

Open your diagram, go to:
Design > Diagram > Options > Change Type...

Make sure it's an Archimate type.

Edit: I think I misunderstood the question, sorry. I don't think the Office MDG is dependent on the diagram type.

3
Hello!

(using JScript)

I initialize CSV-import:

Code: [Select]
    try
    {
        CSVIImportFile(fileName, firstRowContainsHeadings); // See EAScriptLib.JScript-CSV
    }
    catch (error)
    {
        log(true, "Error importing CSV file. Is the path correct? Is the file open?");
        log(true, "Stopping script...");
        log(true, "====================END====================");
        return;
    }

Then in OnRowImported() I check for my defined columns:
Code: [Select]
function OnRowImported()
{
if (!checkForColumns(columns))
{
log(true, "Column not found, stopping script...");
return;
}
...

where checkForColumns() uses CSVIContainsColumn() from EAScriptLib.JScript-CSV:
Code: [Select]
...
if (CSVIContainsColumn(column) == false)
...

However, CSVIContainsColumn(column) always returns false for the first column.

Example CSV:
Code: [Select]
first;second;
1;2;
a;b;

I define my variable columns as
Code: [Select]
columns = ['first', 'second'];
The function from EAScriptLib.JScript-CSV returns false:
Code: [Select]
CSVIContainsColumn('first') -> false

If I however add a dummy column in the beginning, like:
Code: [Select]
zero;first;second;
;1;2;
;a;b;

then
Code: [Select]
CSVIContainsColumn('first') -> true

Later, after importing and creating elements, I add the GUIDs of said elements back to the CSV.

But I discard the dummy-column, so after import and export the CSV looks like this:
Code: [Select]
first;second;guid;
1;2;guid1;
a;b;guid2;

Then all of a sudden CSVIContainsColumn('first') -> true without the dummy column...

I have no idea what's going on and don't know how to troubleshoot this. Hopefully someone can follow my explanation.

Can it have anything to do with different types of CSV's? In Excel there are options for (at least for me):
  • CSV-UTF-8
  • CSV
  • CSV (Macintosh)
  • CSV (MS-DOS)

Is there a known bug using EAScriptLib.JScript-CSV and specifically CSVIContainsColumn()?

Any help or pointers appreciated! Thanks!

I'm on version 16.0.1604

4
I would script a custom csv import, using the csv's guid as some kind of external id. I would let EA create the element, thus give it a new guid. The other fields I would save either as existent standard-fields, like 'Application' would probably be name, and 'Criticality' a tagged value.

5
General Board / Remove ctrl+9 hotkey
« on: November 10, 2023, 08:01:31 pm »
Hello!

When I write scripts I press ctrl+alt+9 to make ] on my keyboard layout.

However, EA always opens the 'Discuss & Review' window, with the hotkey ctrl+9.

I've been here:
https://sparxsystems.com/enterprise_architect_user_guide/16.1/the_application_desktop/customizekeyboardshortcuts.html

But I can't find the ctrl+9 hotkey.

The ctrl+9 hotkey is deocumented here:
https://sparxsystems.com/enterprise_architect_user_guide/16.1/the_application_desktop/keyboardshortcuts.html


When I go to:
Start > Appearance > Preferences > Other Options > Keyboard
Element > Discussion

which I think is the hotkey is, it's empty, no assigned hotkey.

I can't for the love of god not find where ctrl+9 is assigned and remove it.

Any help?

Thanks!

6

Quote
💡One idea that pops up is to create a connector (maybe «trace»?) between the requirement to the performer and activity. And before creating a requirement, check if there is a corresponding requirement for the performer and activity in focus. If there is a requirement, just update the requirement text.
mmh? that sounds like extra work and in a large project likely to become unsustainable.
Rather than create a requirement element why not just generate the requirement via document generation. You've already modelled «OperationalPerformer» --- IsCapableToPerform --> «OperationalActivity»
so it shouldn't be too hard to create a MS Word document that transposes that into
The system shall enable «OperationalPerformer» to «OperationalActivity».
You may need to create a document fragment to achieve that with some SQL behind the scenes.


Well, we need a status of the requirement, approved/implemented/verified/validated etc and also an ID. Therefore I don't think it's enough to only generate the requirement in the document. With a seperate object for the specific requirement based on OperationalPerformer and OperationalActivity we can do that easily.

I don't see we can do that with only generating text in the document. How would we keep track of status and ID?

What I do atm is to wait with generating the requirements as long as possible, then handle the changes and new stuff manually.

Thanks for your input.

7
I'm using EA-Matic to automatically save my scripts to disk when updating them.

Then I use Github desktop to commit them.

Before EA-Matic I used a script to save all my scripts to disk. (and then Github Desktop)

You can't create submenus in the context menu. I try to only keep the most commonly used scripts available in the context menu.
And also make sure to use things like element or package groups instead of project browser group.

Geert

Thank you, will look into that!

8
Hello!

I'm getting a lot of scripts in EA.

How do you version control your scripts?

Do you copy and paste your scripts in an external tool e.g.Visual Studio Code and have that repository version controlled, like git? Or do you have the version control in Sparx EA directly?

Also, can I create 'folders' when right-clicking -> Specialize -> Scripts? That list showing up is getting way to big.

Thank you!

9
Hello!

I use NAFv4 and have modelled Operational Views with the following:

«OperationalPerformer» --- IsCapableToPerform --> «OperationalActivity»

From this I create stakeholder requirements with the following syntax:

The system shall enable «OperationalPerformer» to «OperationalActivity».

I know seems like a waste, but it's a government agency 😇 "it has to be textual requirements"

🤔I just wanted to know if someone have any ideas of how I can keep track of which performers and acitvities which have requirements. My thought is to be able to generate these requirements when there are changes in the Operational Views. E.g. a new performer, or added activities to an existing performer.

💡One idea that pops up is to create a connector (maybe «trace»?) between the requirement to the performer and activity. And before creating a requirement, check if there is a corresponding requirement for the performer and activity in focus. If there is a requirement, just update the requirement text.

❓Any thoughts of how I can implement such a thing, and is the connector approach any good? Is there another way?

Thank you!

10
I've never found an easy way to do this, and Geert's suggestion would make it easy. But I've never found such options.

I document specific diagrams with 'Document Script'.

  • I have a template with a fragment
  • The fragment uses Custom Query -> Document Script
  • Document Script selects and calls a script which contains the logic to document correct diagram

To get you started with the Document Script:
Create a EA.DocumentGenerator: https://sparxsystems.com/enterprise_architect_user_guide/16.1/add-ins___scripting/document_generator_interface_class.html
Code: [Select]
Repository.CreateDocumentGenerator();
Create the logic to find the correct diagram, then use 'DocumentDiagram(...)' from the link above.

Generate as RTF:
Code: [Select]
GetDocumentAsRTF();
A limitation with this approach if using SQL search on the Model Document, is that you must search for an element (as far as I know).

So what I do is usually have an guid-based search for element, then find diagram occurences, or child diagrams in the script, with if statements for types names etc to find my diagram of choice.

The Document Script input parameters I usually have main(objectID, diagramName/diagramType/whatever). Sometimes depending on occasion I only have main(objectID), or main(diagramID).

This seems a bit complicated for just documenting a specific diagram. But this is how I do it.

I have Document Scripts for different scenarios:
  • showDiagramOfType
  • showDiagramOfName

Or just have diagrams in seperate packages, but is not always optimal/wanted.

11
As per usual Geert is right. And just to clarify:

The secret sauce is to aggregate before the join. This removes the need to aggregate in the first SELECT statement.

In my example it would be:

Code: [Select]
LEFT JOIN (
SELECT GROUP_CONCAT(AGG_TABLE.IK_ID, '; ') AS IK_ID, AGG_TABLE.DERIVE_END
FROM (
SELECT IK_ID.Value AS IK_ID, DERIVE.Start_Object_ID AS 'DERIVE_END', IK.Object_ID AS IK_OID
FROM t_object IK
INNER JOIN t_objectproperties IK_ID ON IK_ID.Object_ID = IK.Object_ID AND IK_ID.Property = 'id'
INNER JOIN t_connector DERIVE ON DERIVE.End_Object_ID = IK.Object_ID AND DERIVE.Stereotype = 'deriveReqt'
WHERE IK.Package_ID IN (#Branch='{20273ECC-AB9C-43e3-8E6D-43E7DD60F3AC}'#)
AND IK.Stereotype = 'Intressentkrav'
GROUP BY IK_ID.Value, DERIVE.Start_Object_ID, IK.Object_ID)
AS AGG_TABLE
GROUP BY AGG_TABLE.DERIVE_END)
IK_TABLE ON IK_TABLE.DERIVE_END = SK_TABLE.SK_OID


Full SQL:
Code: [Select]
SELECT SK_TABLE.CLASSGUID, SK_TABLE.CLASSTYPE,
SK_TABLE.SK_ID AS SK_ID,
SK_TABLE.SK_KAPITEL AS SK_KAPITEL,
SK_TABLE.SK_TEXT AS SK_TEXT,
COALESCE(IK_TABLE.IK_ID, '---') AS IK_ID,
COALESCE(GROUP_CONCAT(SE_TABLE.NAME, '; '), '---') AS SE_NAME

FROM
(SELECT SK.ea_guid AS CLASSGUID, SK.Object_Type AS CLASSTYPE, SK.Object_ID AS SK_OID,
SK_ID.Value AS SK_ID, SK_PACKAGE.Name AS SK_KAPITEL, SK_TEXT.Notes AS SK_TEXT
FROM t_object SK
INNER JOIN t_objectproperties SK_ID ON SK_ID.Object_ID = SK.Object_ID AND SK_ID.Property = 'id'
INNER JOIN t_objectproperties SK_TEXT ON SK_TEXT.Object_ID = SK.Object_ID AND SK_TEXT.Property = 'text'
INNER JOIN t_package SK_PACKAGE ON SK_PACKAGE.Package_ID = SK.Package_ID
WHERE SK.Package_ID IN (#Branch='{4FD8BE48-EE95-44ae-ACCB-A7CE7851EB7C}'#)
AND SK.Stereotype = 'Systemkrav')
SK_TABLE

LEFT JOIN (
SELECT GROUP_CONCAT(AGG_TABLE.IK_ID, '; ') AS IK_ID, AGG_TABLE.DERIVE_END
FROM (
SELECT IK_ID.Value AS IK_ID, DERIVE.Start_Object_ID AS 'DERIVE_END', IK.Object_ID AS IK_OID
FROM t_object IK
INNER JOIN t_objectproperties IK_ID ON IK_ID.Object_ID = IK.Object_ID AND IK_ID.Property = 'id'
INNER JOIN t_connector DERIVE ON DERIVE.End_Object_ID = IK.Object_ID AND DERIVE.Stereotype = 'deriveReqt'
WHERE IK.Package_ID IN (#Branch='{20273ECC-AB9C-43e3-8E6D-43E7DD60F3AC}'#)
AND IK.Stereotype = 'Intressentkrav'
GROUP BY IK_ID.Value, DERIVE.Start_Object_ID, IK.Object_ID)
AS AGG_TABLE
GROUP BY AGG_TABLE.DERIVE_END)
IK_TABLE ON IK_TABLE.DERIVE_END = SK_TABLE.SK_OID

LEFT JOIN (
SELECT SE.Name AS NAME, SATISFY.End_Object_ID AS SATISFY_END
FROM t_object SE
INNER JOIN t_connector SATISFY ON SATISFY.Start_Object_ID = SE.Object_ID AND SATISFY.Stereotype = 'satisfy'
WHERE SE.Package_ID IN (#Branch='{95E5A654-A217-4122-B011-045E9F7A720D}'#)
AND SE.Stereotype = 'OperationalPerformer')
SE_TABLE ON SE_TABLE.SATISFY_END = SK_TABLE.SK_OID

GROUP BY SK_TABLE.CLASSGUID
ORDER BY LENGTH(SK_TABLE.SK_ID), SK_TABLE.SK_ID

'Pseudo SQL':
Code: [Select]
LEFT JOIN (
SELECT GROUP_CONCAT(TEMP_TABLE.VALUE, 'delimeter') AS VALUE, TEMP_TABLE.JOIN_VALUE AS JOIN_VALUE
FROM (
-- SQL QUERY
)
AS TEMP_TABLE
GROUP BY TEMP_TABLE.JOIN_VALUE)
MAIN_TABLE ON MAIN_TABLE.JOIN_VALUE = OTHER_TABLE.JOIN_VALUE

Thank you Geert!

12
Indeed, but the regex implementation depends on the scripting engine, not on the database you are using.

There will not be a difference when executing a regex on a .eap model vs a .qea model.

Geert

Well, the only thing I changed in the script was the regex.. Perhaps the text in the tagged value on the 'ModelView' -> 'ViewProperties' is different hence the need to change regex.. I have no idea 🤣

13
Which database?

In recent SQL Server you can use the function STRING_AGGREGATE to group your requiements into a single row.

Here's an example from one of my queries:

Code: [Select]
select * from
(select distinct
(select STRING_AGG( u.Name, char(10))
from t_connector c
inner join t_object u on u.Object_ID = c.Start_Object_ID
and u.Stereotype = 'EAM_Contact'
and exists (select gd.Connector_ID from t_connector gd
where gd.Start_Object_ID = u.Object_ID
and gd.Stereotype = 'ArchiMate_Aggregation'
and gd.End_Object_ID in ("& domain.ElementID &")
)
inner join t_objectproperties tv on tv.Object_ID = u.Object_ID
and tv.Property = 'IsDisabled'
and isnull(tv.Value, 'False') <> 'True'
where c.Stereotype = 'ArchiMate_Assignment'
and c.End_Object_ID = f.FunctionID
 ) as Users
,f.FunctionName
,f.FunctionDescription
,(select STRING_AGG( dep.Name, char(10))
from t_connector c
inner join t_object dep on dep.Object_ID = c.End_Object_ID
and dep.Stereotype = 'ArchiMate_BusinessCollaboration'
where c.Stereotype = 'ArchiMate_Aggregation'
and c.Start_Object_ID = f.FunctionID
 ) as DeelVan
,f.RoleName
, f.RoleDescription
,cg.Name as BusinessRoleGroup
from
       (select cg.Object_ID, cg.Name, cg.Note
       from  t_object cg
       where cg.Stereotype = 'EAM_UserGroup'
       and cg.Name like 'BG%'
   and exists (select gd.Connector_ID from t_connector gd
where gd.Start_Object_ID = cg.Object_ID
and gd.Stereotype = 'ArchiMate_Aggregation'
and gd.End_Object_ID in ("& domain.ElementID &")
)
   ) cg
full outer join
       (select distinct cp.Start_Object_ID
   ,f.Object_ID as FunctionID
   ,f.Name as FunctionName
   ,f.Note as FunctionDescription
   ,pr.Name as RoleName
   ,pr.Note as RoleDescription
       from t_object f
       left join t_connector cf on f.Object_ID = cf.End_Object_ID
                                        and cf.Stereotype = 'trace'
       left join t_object pr on  cf.Start_Object_ID = pr.Object_ID
                                        and pr.Stereotype = 'PartnerRole'
       left join t_connector cp on  pr.Object_ID = cp.End_Object_ID
                                        and cp.Stereotype = 'EAM_UserGroupMember'
       where f.Stereotype = 'EAM_Function'
       ) f on f.Start_Object_ID = cg.Object_ID
) f
order by isnull(f.FunctionName, 'ZZZ'), isnull(f.RoleName, 'ZZZ')

Geert

I'm sorry. This is a local QEAX-file hence SQLite.

Yes, I know how to group, this line does that (combined with COALESCE if null):
Code: [Select]
COALESCE(GROUP_CONCAT(IK_TABLE.IK_ID, '; '), '---') AS IK_ID,

The problem is that the group duplicates values when I add the LEFT JOIN to find elements with the 'satisfy'-relationship.

Without system elements I get:
23; 45; 59

as expected. But when I add the LEFT JOIN for system elements, the above group gets duplicated the number of times a system element is found.

So if the LEFT JOIN finds one system element the output is still:
23; 45; 59

If the LEFT JOIN finds two system elements the group will be:
23; 45; 59; 23; 45; 59

and so on.

I would like it to output:
23; 45; 59

regardless of how many system elements are found.

I don't really understand why this is happening because the stakeholder requirements and system elements are not directly related to each other with connectors, they always go through the system requirement.

14
In case you were not aware: https://regex101.com

q.

Thanks, I usually use https://regexr.com/

Just seems really strange that the regex worked in one environment, and not another...

15
Hello!

I have a query where I get all requirements in a branch.

Then I left join with another group or requirements and LEFT JOIN based on connector (deriveReqt).

Then I left join again with a group of system element and LEFT JOIN based on connector (satisfy).

So the setup is the following:

Code: [Select]
(system element) -- satisfy --> (system requirement) -- deriveReqt --> (stakeholder requirement)
Initially my output was two columns, one for ID of system requirements, and one for related stakeholder requirements which was grouped so the output would be something like this example:

System requirement ID | derived Stakeholder requirement ID
1 | 3
2 | 5, 8
3 | 6, 11
4 | 1, 7

But when I added a third column with system elements which satisfy the system requirements, the stakeholder column gets duplicated with the number of related system elements, for example:

System requirement ID | derived Stakeholder requirement ID | System element
1 | 3 | SE-1
2 | 5, 8, 5, 8 | SE-1, SE-2
3 | 6, 11 | SE-3
4 | 7, 7, 7 | SE-1, SE-2, SE-3

I can clearly see the connection between duplication of 'derived Stakeholder requirement ID' and the number of related 'System element'.

But I have no idea how I fix that.

The desired output would be:

System requirement ID | derived Stakeholder requirement ID | System element
1 | 3 | SE-1
2 | 5, 8 | SE-1, SE-2
3 | 6, 11 | SE-3
4 | 7 | SE-1, SE-2, SE-3

Full SQL:
Code: [Select]
SELECT SK_TABLE.CLASSGUID, SK_TABLE.CLASSTYPE,
SK_TABLE.SK_ID AS SK_ID,
SK_TABLE.SK_KAPITEL AS SK_KAPITEL,
SK_TABLE.SK_TEXT AS SK_TEXT,
COALESCE(GROUP_CONCAT(IK_TABLE.IK_ID, '; '), '---') AS IK_ID,
COALESCE(GROUP_CONCAT(SE_TABLE.NAME, '; '), '---') AS SE_NAME

FROM
(SELECT SK.ea_guid AS CLASSGUID, SK.Object_Type AS CLASSTYPE, SK.Object_ID AS SK_OID,
SK_ID.Value AS SK_ID, SK_PACKAGE.Name AS SK_KAPITEL, SK_TEXT.Notes AS SK_TEXT
FROM t_object SK
INNER JOIN t_objectproperties SK_ID ON SK_ID.Object_ID = SK.Object_ID AND SK_ID.Property = 'id'
INNER JOIN t_objectproperties SK_TEXT ON SK_TEXT.Object_ID = SK.Object_ID AND SK_TEXT.Property = 'text'
INNER JOIN t_package SK_PACKAGE ON SK_PACKAGE.Package_ID = SK.Package_ID
WHERE SK.Package_ID IN (#Branch='{4FD8BE48-EE95-44ae-ACCB-A7CE7851EB7C}'#)
AND SK.Stereotype = 'Systemkrav')
SK_TABLE

LEFT JOIN
(SELECT IK_ID.Value AS IK_ID, DERIVE.Start_Object_ID AS 'DERIVE_END'
FROM t_object IK
INNER JOIN t_objectproperties IK_ID ON IK_ID.Object_ID = IK.Object_ID AND IK_ID.Property = 'id'
INNER JOIN t_connector DERIVE ON DERIVE.End_Object_ID = IK.Object_ID AND DERIVE.Stereotype = 'deriveReqt'
WHERE IK.Package_ID IN (#Branch='{20273ECC-AB9C-43e3-8E6D-43E7DD60F3AC}'#)
AND IK.Stereotype = 'Intressentkrav')
IK_TABLE ON SK_TABLE.SK_OID = IK_TABLE.DERIVE_END

LEFT JOIN (
SELECT SE.Name AS NAME, SATISFY.End_Object_ID AS SATISFY_END
FROM t_object SE
INNER JOIN t_connector SATISFY ON SATISFY.Start_Object_ID = SE.Object_ID AND SATISFY.Stereotype = 'satisfy'
WHERE SE.Package_ID IN (#Branch='{95E5A654-A217-4122-B011-045E9F7A720D}'#)
AND SE.Stereotype = 'OperationalPerformer')
SE_TABLE ON SE_TABLE.SATISFY_END = SK_TABLE.SK_OID

GROUP BY SK_TABLE.CLASSGUID
ORDER BY LENGTH(SK_TABLE.SK_ID), SK_TABLE.SK_ID

Any pointers of how I would fix that would be appreciated!

When googling I found something using WITH, but IIRC SQL statements in Sparx EA MUST start with SELECT so didn't even bother to try it out.

Cheers!

Pages: [1] 2 3 ... 13