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 - Daiim

Pages: [1] 2 3 4
1
Geert, thank you! Works great, even if it adds some complexity.

Best regards,
Daniel

2
For recursion and graph pattern matching use the custom script variant (jscrip, vbscript or javascript) instead of sql queries. For documentation see: https://sparxsystems.com/enterprise_architect_user_guide/17.1/model_publishing/custom_script_fragments.html (here is an example of the expected return format: https://sparxsystems.com/enterprise_architect_user_guide/17.1/model_publishing/example_output_of_an_rtf_templ.html). You can use the xml node names inside the <Row></Row> node via "insert custom fields" inside your template. For multiple results, repeat the <Row></Row> node.

3
Hi all,

using the EA API there is an attribute called StereotypeEx that includes all Stereotypes of a given EA.Element as a comma separated list in a string.
I need to check for a certain Stereotype via SQL Query but the t_object obj.Stereotype only returns the first being set in model. How can I fetch (or better check) the other ones via SQL?

Thank you very much for any hint!

Best regards,
Daiim

4
Can you be a bit more precise please?

Code: [Select]
SELECT
    source.Name as 'Some Name'
FROM t_object source
    LEFT JOIN t_connector link1 ON (link1.Start_Object_ID = source.Object_ID AND link1.Connector_Type = 'Aggregation')
   LEFT JOIN t_object target ON (link1.End_Object_ID = target.Object_ID)
WHERE
   target.Object_ID = 1097

You can go on with additional LEFT JOINS to query for a path. You should not rely on the Object_ID as this is not your model element identity but a database related key that may and will change!

5
I define a model document with a custom template.
The document generator iterates over all elements of one or more package elements that I've assigned to the model document as attributes.

For each element in this package, I'd like to aggregate a set of elements from the model using a template fragment and a custom script (or SQL query).

My question now is: What does the SQL query or custom script need to return so that the Document Generator iterates over this result set and I can use the fields Element.Notes, Element.Name, etc.? I've tried EAGUID, ElementGUID, etc. - that doesn't seem to be sufficient.

Current Idea:
Model Document for Package A --> Document Generator iterates over all Elements of Package A --> Script Template is called for each Element E1..n --> Script Template selects Elementset ES1 for Element E1 .. ESn for Element En --> Script Template uses <Element.Name> for each Element inside the Elementset (..?)

What am I missing?

Thanks for your help and any hint or tip.

Daiim




6
Thank you Geert, this was the point.  :D

7

I try to generate a table of neighbors for a given element via document generation, but only get one entry as a result.
The document template is called for each element and uses a Custom Query (more precise a Custom Script) being called with the #OBJECTID# as parameter.
The script iterates over all neighbors via API and returns a XML for a list of entities, e.g. { Application : "Sparx EA", Vendor: "SparxSystems", Homepage: "https://sparxsystems.com" }.

The XML structure is:
Code: [Select]
<?xml version="1.0" encoding="UTF-8"?>
<EADATA>
    <Dataset_0>
        <Data>
            <Row>
                <Application>Sparx EA</Application>
                <Vendor>SparxSystems</Vendor>
                <Homepage>http://sparxsystems.com</Homepage>
            </Row>
        </Data>
    </Dataset_0>
    <Dataset_1>
        <Data>
            <Row>
                <Application>Word</Application>
                <Vendor>Microsoft</Vendor>
                <Homepage>https://microsoft.com</Homepage>
            </Row>
        </Data>
    </Dataset_1>
</EADATA>

The script template uses a table with a table header and a single row with the custom fields {Application}, {Vendor} and {Homepage}.
What must I do, that all results (Dataset_0 to Dataset_i) are rendered as rows into the table?

Thank you very much for any hint or tip!

Best regards,
Daiim

8
Can I suggest Repository.CurrentSelection, which gives you more information about what is selected.

EASelection Class

It will tell you that the selection is on the diagram (selection.Location == "Diagram"), the element being displayed in all the properties windows, (selection.Context) and the full list of the elements in that selection. (selection.List)

Those are all properties that are available without additional database queries. You can use them in locations like building menus or update commands without negatively impacting performance. The final significant property for that object is the ElementSet, which will load all of the selected objects. It will be a faster way of accessing all of the selected objects than calling Repository.GetElementByID or Repository.GetElementByGuid for each item individually.

Great, thank you for this hint. Sorrowly I have no intellisense/context in the script editor for an variable declared with "var selection as EASelection;". It is quite plodding to switch between documentation and coding.

9
The problem with GetContexObject is that the object could be selected anywhere, including the browser, so I suggest you use this method to get the GUID (or ID) of the selected object, then use Diagram.SelectedObjects, iterate and select the matching object from GetContextObject (if no match then the object has been selected else where).

That should get you to the element (object) you are after

Correct. But as the script runs in the context "Diagram" (as every script in the "Diagram Script Group"), this is not an issue in this case. So EA.Diagram.SelectedObjects gives me every selected DiagramObject and EA.Repository.GetContextObject() provides the primary object (precise EA.Element).

For everyone in the community, here is the code to BulkLink elements on a Diagram according to settings in a config object defined hard-coded in the script.
To run this create a JScript in a "Diagram Group" within the script window (name can be choosen as you like and must not be equal to the function name inside the script).

Code: [Select]
function OnDiagramScript()
{
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();

if ( currentDiagram == null ) {
Session.Output("No diagram is selected. Done.");
return;
}

var selectedObjects as EA.Collection;
selectedObjects = currentDiagram.SelectedObjects;

if (selectedObjects.Count <= 0) {
Session.Output("No object is selected. Done.");
return;
}

if (selectedObjects.Count == 1) {
Session.Output("At least 2 objects MUST be selected. Done.");
return;
}

var primaryElement as EA.Element;
primaryElement = Repository.GetContextObject();

if (primaryElement == null) {
Session.Output("Could not find primary selection. Done.");
return;
}

for (var index = 0; index < selectedObjects.Count; index++)
{
var currentObject as EA.DiagramObject;
currentObject = selectedObjects.GetAt(index);

var currentElement as EA.Element;
currentElement = Repository.GetElementByID(currentObject.ElementID);

if (primaryElement.ElementID == currentElement.ElementID)
continue;

var link as EA.Connector;

if (linkDef.LinkDirection === undefined)
linkDef.LinkDirection = "ToPrimary";

if (linkDef.LinkDirection == "ToPrimary") {
link = LinkElementFromTo(currentElement, primaryElement, linkDef);
}
else {
link = LinkElementFromTo(primaryElement, currentElementElement, linkDef);
}

if (link == null) {
Session.Output("Failed to create link from '" + currentElement.Name + "' to '"+ primaryElement.Name +"'.");
}
}

Repository.ReloadDiagram(currentDiagram.DiagramID);
}

var linkDef = {
LinkName : "enhances",
LinkType : "Association",
LinkStereotype : "Application Function",
LinkDirection : "ToPrimary"
};

Repository.EnsureOutputVisible("Script");

OnDiagramScript(linkDef);

And the function that links two elements:
Code: [Select]
function LinkElementFromTo(sourceElement, targetElement, linkDef)
{
if (sourceElement == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @SourceElement is null." };
throw msg;
}

if (targetElement == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @TargetElement is null." };
throw msg;
}

if (linkDef == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @LinkDef is null." };
throw msg;
}


var source as EA.Element;
var target as EA.Element;

source = sourceElement;
target = targetElement;

//Session.Output("Source: " + source.Name + ", ID: " + source.ElementID);
//Session.Output("Target: " + target.Name + ", ID: " + target.ElementID);

var link as EA.Connector;

if (linkDef.LinkName === undefined)
linkDef.LinkName = "";

if (linkDef.LinkType === undefined)
linkDef.LinkType = "Association";

link = source.Connectors.AddNew(linkDef.LinkName, linkDef.LinkType);

if (link == null) {
var msg = { Source : "LinkElementFromTo::_Elements.AddNew", Error : "Failed to create link." };
throw msg;
}

if (linkDef.LinkStereotype !== undefined)
link.StereotypeEx = linkDef.LinkStereotype;

link.ClientID = source.ElementID;
link.SupplierID = target.ElementID;

link.Update();

source.Elements.Refresh();
target.Elements.Refresh();

return link;
}

10
Thank you Geert for your hint.

The z-order is not the solution (for DiagramObject it's the property 'Sequence') but this raised an idea that gave the solution:

  • it's the EA.Repository.GetContextObject() that gives you the EA.Element that is selected primary if you've selected a set of DiagramObjects on a Diagram. You can check the type of the context with EA.Repository.GetContextItemType()

Documentation is here: https://sparxsystems.com/enterprise_architect_user_guide/17.0/add-ins___scripting/repository3.html

Only side-question left: how to use EA.Repository.GetContextItem(object item) and what is it used for? I got no idea from the description in the documentation.

Thanks for all and best regards!
Daiim

11
Hello together,

I try to figure out via (J)Script, which of the element in the currentDiagram.SelectedObjects is the primary one (the object with the dashed frame around it that is also used for alignment). What I already tried:

- guessed, it is the first one in the collection (it is not)
- using the coordinates of the DiagramObject (top, left, right, bottom) and try to match the mouse point
- try to figure out what the undocumented function HitTest(string, number) @EA.Diagram does

Has anyone a tip for me?

Thank you very much!
Daiim

12
Client* is the source, where the connector starts, and Supplier* (nobody knows why this is named like that) is the connectors target, where it points to! Keep attention to the connector type as the semantic direction may be the other way around. This is (sometimes) defined by the 'direction' property of the connector.

13
I always try this in a <<Model View>> first, and then I use this in code via API (Repository.SQLQuery) with JScript. In this case, the EA Editor of the Model View already complains with the syntax error. I'm using an local EAP file (DB Version 4.01).

14
Hi there,

the knowledge of existing relations in a model is as important as the knowledge of relations that are explicitly missing between some object types. I try to figure out how to express this within an SQL Query.

Example 1)
Elements that have a port with a certain tagged-value I can query the following way:
Code: [Select]
SELECT element.ea_guid AS GUID
FROM ((t_object element
    LEFT JOIN t_object port ON (port.ParentID = element.Object_ID))
    LEFT JOIN t_objectproperties tag ON (tag.Object_ID = port.Object_ID))
WHERE <element filter criteria> AND <port filter criteria> AND tag.Property = '<TaggedValue-Name>'

Now I try to find a way to query for elements that explicitly do not have these relations. Usually I would create a set A with all elements that have the <element filter criteria> and a set B with elements that have the tagged value relation to finally create the result via A except B.

My expectation would be, that a query using EXCEPT (https://www.techonthenet.com/sql/except.php) would give me what I want:
Code: [Select]
SELECT other.ea_guid AS CLASSGUID, other.Name AS Name
FROM t_object other
WHERE <element filter criteria>
EXCEPT
SELECT element.ea_guid AS CLASSGUID, element.Name AS Name
FROM ((t_object element
    LEFT JOIN t_object port ON (port.ParentID = element.Object_ID))
    LEFT JOIN t_objectproperties tag ON (tag.Object_ID = port.Object_ID))
WHERE <element filter criteria> AND <port filter criteria> AND tag.Property = '<TaggedValue-Name>'

But EA complains about a missing operator (in the first WHERE clause). What am I doing wrong?

15
General Board / Re: DAO.Field [3036] / [3001] Error
« on: May 18, 2022, 08:57:57 pm »
Excel and Access are no tools to do professional Architecture.
We both agree on that. But as an consultant my job is to support the customer to improve. And even the environment is not optimal, it works. Could be better - for sure - but complaining is no solution. And even EA is far from optimal in many things necessary for scalable architectural work. But it's the best tool I know of, so I use it and do not complain about it's drawbacks. But I'm open for job offers, if you alluded to it.  ;)

After trying a couple of solution approaches I guess I found the origin of the problem. The import logs are pushed to an EA artifact's note attribute. As they can be quite long, entries exceeding a certain length seem to blow up the database. Deleting the artifact or notes value did not help. But after roling back the import, and do it again with stronger filter rules - resulting in a smaller log - did not cause an error on extending the scripts.
Strange behaviour and confusing, as setting Notes did not cause any exception or db error, but the problem seems to be solved.

Lessons learned: EA.Element.Notes attribute (much likely any Notes attribute) does not tolerate too much text. ^^

Pages: [1] 2 3 4