BCMS.qea Enterprise Architect project ver. 17.x
Currency.Java.qea Enterprise Architect project ver. 17.x
Hyperlink.qea Enterprise Architect project ver. 17.x
Scripting.qea Enterprise Architect project ver. 17.x
Scripting ☛ is an internal Automation Interface based on, for instance, JavaScript, to deal with the Object Model ☛ Enterprise Architect also supports an external Automation Interface based on, for instance, Java
Specialize⇝Script Library -Tools-⤳ list of (extant) adaptable scriptsDevelop⇝Execution Analyzer -Source Code-⇝Edit Analyzer Scripts -Scripts-orExecute⇝Analyzer -Tools-⇝View Analyzer Scripts
Java setup within Windows 11
"C:\Program Files\Sparx Systems\EA\Java API\SSJavaCOM64.dll"copied toC:\Windows\System32"C:\Program Files\Sparx Systems\EA\Java API\eaapi.jar"as Java libraryExample (Java Maven project
)
public class Enterprise_Architect_Java_API { public static void main(String[] args) { // 'ea' directory as repository... // See POM for 'ea' repository setup // -right click- (project) >> Run Maven >> Goals... // deploy:deploy-file -DgroupId=org.sparx -DartifactId=ea -Dversion=1.0 -Durl=file:./ea/ -DrepositoryId=ea -DupdateReleaseInfo=true -Dfile=./lib/eaapi.jar System.out.println("Java working directory: " + System.getProperty("user.dir")); org.sparx.Repository model = new org.sparx.Repository(); System.out.println("'model.GetIsSecurityEnabled()': " + model.GetIsSecurityEnabled()); // 'false' model.OpenFile("C:\\Users\\franc\\Desktop\\BCMS.qea"); // Get the repository from execution *WITHIN* Enterprise Architect: // model = org.sparx.Services.GetRepository(processID); // 'processID' of Enterprise Architect execution instance is passed automatically... org.sparx.Collection<org.sparx.Package> packages = model.GetModels(); for (short i = 0; i < packages.GetCount(); i++) { org.sparx.Package p = packages.GetAt(i); // model.WriteOutput("Script", p.GetName(), 0); // Write 'Script' tab of 'System Output' window... System.out.println(p.GetName() + " is a model as root package..."); } // Database may be locked when security is enabled, so SQL 'UPDATE' may fail: model.Execute("UPDATE t_object SET Status = 'Approved' WHERE Object_Type = 'Package';"); model.Execute("UPDATE t_object SET GenType = NULL;"); model.Execute("COMMIT;"); model.CloseFile(); model.Exit(); } }
Example (Python file
)
# EA.py print("Enterprise Architect with PYTHON...") from singleton_decorator import singleton # https://pypi.org/project/singleton-decorator/ -> 'pip install singleton-decorator' import time import win32com.client # 'pip install pywin32' @singleton class Enterprise_Architect: def __init__(self): try: self._EA = win32com.client.DispatchEx("EA.App") # Kill EA instance in Windows 'Task Manager' print("Enterprise Architect instance created...") self._Repository = self._EA.Repository # models = self._Repository.models self._Repository.OpenFile("C:\\Users\\franc\\Desktop\\Age_classification.qea") print("'self._Repository.RepositoryType()': ",self._Repository.RepositoryType()) print("Name of diagram: ",self._Repository.GetDiagramByGuid("{53E40320-B104-4c1f-9243-70E3E1D471B1}").Name) # GUID of 'Age_classification' diagram: {53E40320-B104-4c1f-9243-70E3E1D471B1} time.sleep(1) self._Repository.CloseFile() self._Repository.Exit() print("Enterprise Architect instance stopped... No effect? -> kill EA instance in Windows 'Task Manager'") except Exception as e: print(e) @classmethod def Get_instance(file_URL): repository = win32com.client.GetActiveObject("EA.App").Repository # EA instance is already running... repository.CreateObject("EA.Repository") repository.OpenFile(file_URL) time.sleep(1) repository.CloseFile() repository.Exit() return None ea = Enterprise_Architect() # creates instance ea_ = Enterprise_Architect() # returns same instance because of '@singleton' print(ea == ea_) # 'True'
Key action(s)
Specialize⇝JavaScript -Tools-Example
var zero = Repository.Models.GetByName("Model").ParentID; Session.Prompt(zero,1);![]()
![]()
Key action(s)
Specialize⇝Script Library -Tools-Example
![]()
!INC Local Scripts.EAConstants-JavaScript /* Ajout automatique d'hyperliens sur des objets (étude de cas CIMPA SAS) */ function Hyperlink() { Repository.EnsureOutputVisible("Script"); // Open 'System Output > Script' window for message display... var hyperlinks = new Map(); hyperlinks.set("Franck Barbier","https://FranckBarbier.com"); hyperlinks.set("B--Di","https://BarbierDarnal.com"); // Create a new model root named "Modified model": var root as EA.Package; root = Repository.Models.AddNew("Modified model",""); root.Update(); // Create "Modified hyperlink" child package of "Modified model": var target_package as EA.Package; target_package = root.Packages.AddNew("Modified hyperlink","Class"); // "Class" -> 'Set View Icon...' target_package.Update(); var target_diagram as EA.Diagram; target_diagram = target_package.Diagrams.AddNew("Modified hyperlink","Class"); target_diagram.Notes = "Ajout automatique d'hyperliens sur des objets (étude de cas CIMPA SAS)"; target_diagram.Update(); var source_package = Repository.Models.GetByName("Model").Packages.GetByName("Hyperlink"); // Session.Output("'source_package' count: " + source_package.Elements.Count); // ''source_package' count: 4' hyperlinks.forEach(function(value,key) { var element = source_package.Elements.GetByName(key); if(element) { var element_copy = target_package.Elements.AddNew(element.Name,element.Type); // Copy of original object... // "Text" instead of "Hyperlink" plus customization: var hyperlink = element_copy.Elements.AddNew(value, "Hyperlink"); // element_.Update(); // Update in browser... var element_in_diagram as EA.DiagramObject; element_in_diagram = target_diagram.DiagramObjects.AddNew("",""); // No style at all... element_in_diagram.ElementID = element_copy.ElementID; // Refer to existing object in browser... element_in_diagram.Update(); element_in_diagram = target_diagram.DiagramObjects.AddNew("",""); // No style at all... element_in_diagram.ElementID = hyperlink.ElementID; // Refer to existing hyperlink in browser... element_in_diagram.Update(); } }); // Apply layout: https://sparxsystems.com/forums/smf/index.php?topic=5883.0 } // Test: Hyperlink();![]()
Principle
Enterprise Architect supports predefined events from which a script as “add-in” acts as a subscriber. The list of events is offered as a package named
Broadcast Types.Key action(s)
Add a Model using Model Builder…(package within browser) ⇝Create from pattern⇝Model Add-Ins⇝Broadcast Types- Perspective ⤳
Management⇝Model Add-Ins⤳ creation of a UML Class Diagram in which an “add-in” is modeledSpecialize -Add-Ins-⇝Manage AddinDevelop⇝Behavior -Source Code-⇝Edit BehaviorDevelop -Source Code-⇝Behavior⇝Edit Internal Code
Broadcast Types![]()
Model Add-In ⤳ creation
![]()
Model Add-In ⤳ management ☛
Statusis user-oriented, i.e.,Optionalmeans that users may decide Model Add-In usage or not.![]()
Model Add-In ⤳ Enterprise Architect predefined events (i.e., signals) ☛
- General-purpose
EA_Connect- Etc.
- Model
EA_OnPreDeleteConnectorEA_OnPreDeleteElement☛- Etc.
- Etc.
Model Add-In ⤳ Application Programming Interface -API-
App☛ ⤳ Enterprise Architect running instanceDiagram☛EventProperties☛ObjectType☛Repository☛Session☛- Etc.
Model Add-In ⤳ Enterprise Architect connection handler
![]()
Model Add-In ⤳ Enterprise Architect connection event
![]()
Model Add-In ⤳ execution
Check
Load on Startupfor immediate execution![]()
Exercise
- Based on
EA_OnPreDeleteElementevent ☛ avoid element suppression- Based on
EA_OnPostNewConnectorevent ☛ force cardinality nearby black diamond (UML Composition) to be anything other than0..1or1(Model Validation events ☛ may play an equivalent role as well)Session.Output("EA_OnPostNewConnector..."); // 'return' must be 'true' to get cardinality as '1' or '0..1': return this.EA_OnPostNewConnector_handler(Repository,Info);Session.Output("EA_OnPostNewConnector_handler..."); // Session.Output(Info.ObjectType); '46' -> Connector var connector_id = Info.Get(Info.Count - 1); // Only one... // Session.Output(connector_id); var connector = Repository.GetConnectorByID(connector_id); if(connector.Type === "Aggregation" && connector.Subtype === "Strong") Session.Output("UML BLACK DIAMOND"); if(connector.ClientEnd.Aggregation === 2) { // Composite connector.ClientEnd.Cardinality = "1"; connector.ClientEnd.Role = "-1- or -0..1- only!"; if(connector.ClientEnd.Update() === false) Session.Output(connector.ClientEnd.GetLastError(),1); } else if(connector.SupplierEnd.Aggregation === 2) { // Composite connector.SupplierEnd.Cardinality = "1"; connector.SupplierEnd.Role = "-1- or -0..1- only!"; if(connector.SupplierEnd.Update() === false) Session.Output(connector.ClientEnd.GetLastError(),1); } // connector.Update(); // Useless... return true;
Principle
Search results in XML format after (probable) pre-processing…
Add-In Search signature
![]()
Add-In Search code
![]()
Add-In Search execution
![]()
Principle
Customization of element or connector (look&feel typically) resulting from applied stereotype
Stereotype introduction
Settings⇝UML Types -Reference Data-⤳AssignShape Script toFBnew stereotype![]()
Shape Script
![]()
Usage
![]()
- Download and unzip
Currency.Java.zip![]()
Develop⇝Files -Source Code-⇝Import Source Directory…Expected result
![]()
Exercise
- Add constant public
Dollar_change_rateclass attribute toBitcoinclassDevelop⇝Synchronize -Source Code-⇝Synchronize Package… -Synchronize with Code-⤳Forward engineering (model -> source)- Add
Dinar_algerienas new currency within UML Class Diagram (check thatFilenameEnterprise Architect “Project” property is set up!)Develop⇝Generate -Source Code-⇝Generate Single Element -Generate Code-
Settings⇝Options -Model-⇝Source Code Engineering⇝Default Language for Code Generation![]()
Develop⇝Options -Source Code-⇝Edit Code Template -Templates-Develop⇝Options -Source Code-⇝Reset Source Language… -Configure-![]()
Develop⇝Generate -Source Code-⇝Generate All -Generate Code-![]()
Develop⇝Edit -Source Code-![]()
Expected result
from abc import ABC, abstractmethod class Currency(ABC): def __init__(self,common_symbol,iso_code,iso_symbol): self._common_symbol = common_symbol # Etc. def rate(currency): pass @abstractmethod def to_dollar_rate(): pass def convert_to_dollar(amount): pass @abstractmethod def to_euro_rate(): pass def convert_to_euro(amount): pass Euro = Currency("€", 978, "EUR") # 'TypeError: Can't instantiate abstract class Currency with abstract methods to_dollar_rate, to_euro_rate' print('Euro: ', Euro._common_symbol)Namespaces ☛
Namespaces mainly act as location paths used by code generation especially
-right click-(package within browser) ⇝Develop -Source Code-⇝Options⇝Set as Namespace RootSettings⇝Settings -Reference Data-⇝Namespace Roots…⇝Clear Namespace Attribute(package)