The Script Editor in Astah is a dynamic tool designed to boost your productivity and streamline your workflow. With this feature, you can create custom scripts to automate a range of tasks, from quickly counting blocks within a project to efficiently organizing models based on specific criteria. This flexibility allows for a tailored experience, enhancing analysis capabilities within the Astah environment.
Astah’s built-in Script Editor supports ECMAScript and JEXL. If you’d like to use Groovy language, you can use Model-Driven Script Editor.
In order to access Astah’s Script Editor, simply navigate to [Tools] and then select [Script Editor] from the main menu.
Astah’s Script Editor offers the flexibility of using either ECMAScript or JEXL for scripting, catering to your specific needs and preferences. Easily switch between these languages using the convenient drop-down menu located in the right corner of the Script Editor.
2. Execute the script by navigating to [Action] → [Go] or clicking the [Run] button under the [Action] menu.
3. View the results, which will be displayed in the lower field.
To customize your experience with the Script Editor, you can configure its settings and adjust the font size. These adjustments are accessible through the Settings menu. To open this menu, either navigate to [Help] → [Settings] or click on the gear icon.
Here’re some practical sample scripts you can use!
Please refer to this page for sample scripts.
var IBlock = Java.type("com.change_vision.jude.api.inf.model.IBlock");
blocks = astah.findElements(IBlock.class);
for (var b in blocks) {
print(blocks[b].getName());
}
//This script writes out the information of packages and Blocks.
//The current Astah project should have packages and Blocks.
run();
function run() {
var project = astah.getProject();
printPackageInfo(project);
}
function printPackageInfo(iPackage) {
print("Package name: " + iPackage.getName());
print("Package definition: " + iPackage.getDefinition());
with(new JavaImporter(
com.change_vision.jude.api.inf.model)) {
// Display packages and classes
var namedElements = iPackage.getOwnedElements();
for (var i in namedElements) {
var namedElement = namedElements[i];
if (namedElement instanceof IPackage) {
printPackageInfo(namedElement);
} else if (namedElement instanceof IClass) {
printClassInfo(namedElement);
}
}
}
}
function printClassInfo(iClass) {
print("Class name: " + iClass.getName());
print("Class definition: " + iClass.getDefinition());
// Display all attributes
var iAttributes = iClass.getAttributes();
for (var i in iAttributes) {
printAttributeInfo(iAttributes[i]);
}
// Display all operations
var iOperations = iClass.getOperations();
for (var i in iOperations) {
printOperationInfo(iOperations[i]);
}
// Display inner class information
var classes = iClass.getNestedClasses();
for (var i in classes) {
printClassInfo(classes[i]);
}
}
function printOperationInfo(iOperation) {
print("Operation name: " + iOperation.getName());
print("Operation returnType: " + iOperation.getReturnTypeExpression());
print("Operation definition: " + iOperation.getDefinition());
}
function printAttributeInfo(iAttribute) {
print("Attribute name: " + iAttribute.getName());
print("Attribute type: " + iAttribute.getTypeExpression());
print("Attribute definition: " + iAttribute.getDefinition());
}
run();
function run() {
var targets = searchMessagesWithoutOperation();
if (targets.length === 0) {
print('No target messages found');
return;
}
}
function searchMessagesWithoutOperation() {
with (new JavaImporter(com.change_vision.jude.api.inf.model)) {
var targets = [];
var messages = astah.findElements(IMessage.class);
for (var i in messages) {
var message = messages[i];
if (message.isReturnMessage() || message.isCreateMessage()) {
continue; // ignore
}
var operation = message.getOperation();
if (operation === null) {
targets.push(message);
print('HIT: Message [' + message.getName()
+ '] is Sequence diagram ['
+ message.getPresentations()[0].getDiagram().getFullName('::')
+ ']');
}
}
}
return targets;
}
//This script generates a CSV file about the blocks in the current model.
//CSV format:
// "Name of a Block", "Name of the parent model", "Definition of the class"
run();
function run() {
exportClassesInCsv();
}
function exportClassesInCsv() {
with(new JavaImporter(
com.change_vision.jude.api.inf.model)) {
classes = astah.findElements(IClass.class);
}
var csvFile = selectCsvFile();
if (csvFile == null) {
print('Canceled');
return;
}
print('Selected file = ' + csvFile.getAbsolutePath());
if (csvFile.exists()) {
var msg = "Do you want to overwrite?";
with(new JavaImporter(javax.swing)) {
var ret = JOptionPane.showConfirmDialog(scriptWindow, msg);
if (ret != JOptionPane.YES_OPTION) {
print('Canceled');
return;
}
}
}
with(new JavaImporter(
java.io)) {
var writer = new BufferedWriter(new FileWriter(csvFile));
for(var i in classes) {
var clazz = classes[i];
var rowData = [];
rowData.push(clazz.getName());
rowData.push(clazz.getOwner().getName());
rowData.push(clazz.getDefinition());
writeRow(writer, rowData);
}
writer.close();
}
}
function selectCsvFile() {
with(new JavaImporter(
java.io,
javax.swing)) {
var chooser = new JFileChooser();
var selected = chooser.showSaveDialog(scriptWindow);
if (selected == JFileChooser.APPROVE_OPTION) {
var file = chooser.getSelectedFile();
if (file.getName().toLowerCase().endsWith('.csv')) {
return file;
} else {
return new File(file.getAbsolutePath() + '.csv');
}
} else {
return null;
}
}
}
function writeRow(writer, rowData) {
for (var i in rowData) {
writeItem(writer, rowData[i]);
if (i < rowData.length - 1) {
writer.write(',');
}
}
writer.newLine();
}
function writeItem(writer, data) {
writer.write('"');
writer.write(escapeDoubleQuotes(data));
writer.write('"');
}
function escapeDoubleQuotes(data) {
return data.replaceAll("\"", "\"\"");
}
In order to use TaggedValues, you need to import Profiles.
function printTaggedValueInfo(model) {
if (model == null) {
return
}
var taggedValues = model.getTaggedValues();
for each(var taggedValue in taggedValues) {
print(taggedValue.getKey() + ":" + taggedValue.getValue())
}
}
function printSelectedPresentationsTaggedValueInfo() {
var viewManager = astah.getViewManager()
var diagramViewManager = viewManager.getDiagramViewManager()
var selectedPresentations = diagramViewManager.getSelectedPresentations()
for each(var selectedPresentation in selectedPresentations) {
printTaggedValueInfo(selectedPresentation.getModel())
}
}
※ Show TaggedValue script is also required.
function printSelectedEntitiesTaggedValueInfo() {
var viewManager = astah.getViewManager()
var projectViewManager = viewManager.getProjectViewManager()
var selectedEntities = projectViewManager.getSelectedEntities()
for each(var selectedEntity in selectedEntities) {
printTaggedValueInfo(selectedEntity)
}
}
※ Show TaggedValue script is also required.
var IElement = Java.type('com.change_vision.jude.api.inf.model.IElement');
var Arrays = Java.type('java.util.Arrays');
// Search by stereotype
var stereotype = "stereotype";
for each(var element in astah.findElements(IElement.class)) {
if (containsStereotype(element, stereotype)) {
print(element.getName());
}
}
function containsStereotype(element, stereotype) {
var stereotypes = Arrays.asList(element.getStereotypes())
return stereotypes.contains(stereotype)
}
var infNamespace = 'com.change_vision.jude.api.inf'
var INamedElement = Java.type(infNamespace + '.model.INamedElement');
var TransactionManager = Java.type(infNamespace + '.editor.TransactionManager');
var Key = Java.type(infNamespace + '.presentation.PresentationPropertyConstants.Key');
// Color to change
var COLOR = "#BBCCFF";
// Common Keywords in definition
var IDENTICAL_STRING = "a";
run();
function run() {
var currentDiagram = getCurrentDiagram();
if (currentDiagram == null) {
print("error: Please open a diagram first.");
return;
}
var presentations = getPresentations(currentDiagram);
var chengeColorPresentations = getIdenticalDefinitionPresentations(presentations, IDENTICAL_STRING);
setColor(chengeColorPresentations, COLOR);
}
function getCurrentDiagram() {
try{
var viewManager = astah.getViewManager();
var diagramViewManager = viewManager.getDiagramViewManager();
return diagramViewManager.getCurrentDiagram();
} catch(e) {
return null;
}
}
function getPresentations(currentDiagram) {
try {
return currentDiagram.getPresentations();
} catch (e) {
return new IPresentation[0];
}
}
function getIdenticalDefinitionPresentations(presentations, identicalString) {
var regularExpression = new RegExp("(.*)(" + identicalString + ")(.*)");
var identicalDefinitionPresentations = [];
for(var i in presentations) {
var presentation = presentations[i];
if (presentation == null) {
continue;
}
var model = presentation.getModel();
if (model == null) {
continue;
}
if (!(model instanceof INamedElement)) {
continue;
}
var definition = model.getDefinition();
if (definition.match(regularExpression)) {
identicalDefinitionPresentations.push(presentation);
}
}
return identicalDefinitionPresentations;
}
function setColor(presentations, color) {
try {
TransactionManager.beginTransaction();
for(var i in presentations) {
var presentation = presentations[i];
presentation.setProperty(Key.FILL_COLOR, color);
}
TransactionManager.endTransaction();
print("Done for " + presentations.length + " objects");
} catch (e) {
TransactionManager.abortTransaction();
print("error: Failed");
print(e);
}
}
run();
function run() {
var notes = getAllNotesInDiagramEditor();
if (notes.length === 0) {
return;
}
var TransactionManager = Java.type('com.change_vision.jude.api.inf.editor.TransactionManager');
TransactionManager.beginTransaction();
notes.forEach(function(note) {
deleteElement(note);
});
TransactionManager.endTransaction();
}
function getAllNotesInDiagramEditor() {
var diagramViewManager = astah.getViewManager().getDiagramViewManager()
var diagram = diagramViewManager.getCurrentDiagram();
if (diagram === null) {
print('Open any diagram.');
return [];
}
var presentations = Java.from(diagram.getPresentations());
return presentations.filter(function(p) {
return p.type.equals('Note');
});
}
function deleteElement(presentation) {
var modelEditor = astah.getModelEditorFactory().getBasicModelEditor();
modelEditor.delete(presentation.getModel());
}
//This script generates the setter/getter operations for the selected attributes.
//You should select attributes in the StructureTree before running this.
run();
function run() {
var attributes = getSelectedAttributesInProjectView();
if (attributes.length === 0) {
print('Please select attributes that you want to add setter/getter in StructureTree');
return;
}
with(new JavaImporter(
com.change_vision.jude.api.inf.editor)) {
TransactionManager.beginTransaction();
for (var i in attributes) {
addSetterGetter(attributes[i]);
}
TransactionManager.endTransaction();
}
}
function getSelectedAttributesInProjectView() {
with(new JavaImporter(
com.change_vision.jude.api.inf.model)) {
var attributes = [];
var projectViewManager = astah.getViewManager().getProjectViewManager();
var selectedEntities = projectViewManager.getSelectedEntities();
for (var i in selectedEntities) {
var entity = selectedEntities[i];
if (entity instanceof IAttribute) {
attributes.push(entity);
print('Target attribute: ' + entity.getName());
}
}
}
return attributes;
}
function addSetterGetter(attribute) {
var editor = astah.getModelEditorFactory().getBasicModelEditor();
var clazz = attribute.getOwner();
var attributeName = attribute.getName();
//setter
var setter = editor.createOperation(clazz, getSetterName(attributeName), 'void');
editor.createParameter(setter, attribute.getName(), attribute.getType());
print('Added Setter Operation: ' + setter.getName());
//getter
var getter = editor.createOperation(clazz, getGetterName(attributeName), attribute.getType());
print('Added Getter Operation: ' + getter.getName());
}
function getSetterName(attributeName) {
return 'set' + attributeName;
}
function getGetterName(attributeName) {
return 'get' + attributeName;
}
//This script writes out a list of text in the current mindmap.
//The format is like a WiKi.
var depth = 0;
var INDENT_STR = ' '; //2 spaces
var ITEM_MARKER_STR = '* ';
run();
function run() {
with(new JavaImporter(
com.change_vision.jude.api.inf.model)) {
var diagramViewManager = astah.getViewManager().getDiagramViewManager();
var diagram = diagramViewManager.getCurrentDiagram();
if (!(diagram instanceof IMindMapDiagram)) {
print('Open a mindmap and run again.');
return;
}
var rootTopic = diagram.getRoot();
depth = 0;
printTopics(rootTopic);
}
}
function printTopics(topic) {
var topicLabel = topic.getLabel().replaceAll('\n', ' ');
print(getIndent(depth) + ITEM_MARKER_STR + topicLabel);
var topics = topic.getChildren();
depth++;
for (var i in topics) {
if (topics[i].getType() == 'Topic') { //skip MMBoundary
printTopics(topics[i]);
}
}
depth--;
}
function getIndent(depth) {
var indent = '';
for (var i = 0; i < depth; i++) {
indent += INDENT_STR;
}
return indent;
}
var Key = Java.type('com.change_vision.jude.api.inf.presentation.PresentationPropertyConstants.Key');
var IMindMapDiagram = Java.type('com.change_vision.jude.api.inf.model.IMindMapDiagram');
var TransactionManager = Java.type('com.change_vision.jude.api.inf.editor.TransactionManager');
var level = 0;
var doOpen = undefined;
var TARGET_LEVEL = 1;//Specify the level here
run();
function run() {
var diagramViewManager = astah.getViewManager().getDiagramViewManager();
var diagram = diagramViewManager.getCurrentDiagram();
if (!(diagram instanceof IMindMapDiagram)) {
print('Open a mindmap and run again.');
return;
}
var rootTopic = diagram.getRoot();
try {
TransactionManager.beginTransaction();
reverseTopicVisibility(rootTopic);
TransactionManager.endTransaction();
print('LEVEL' + TARGET_LEVEL + 'Done');
} catch (e) {
TransactionManager.abortTransaction();
print('error: LEVEL' + TARGET_LEVEL + 'Failed');
print(e);
}
}
function reverseTopicVisibility(topic) {
if (isNaN(TARGET_LEVEL) || TARGET_LEVEL < 0) {
throw { toString: function() { return 'TARGET_LEVEL needs to be Integer value'; } };
}
if (level === TARGET_LEVEL) {
if (doOpen == undefined) {
doOpen = topic.getProperty(Key.SUB_TOPIC_VISIBILITY) == 'false';
}
topic.setProperty(Key.SUB_TOPIC_VISIBILITY, doOpen);
}
var topics = topic.getChildren();
level++;
for (var i in topics) {
if (topics[i].getType() =='Topic') { //skip MMBoundary
reverseTopicVisibility(topics[i]);
}
}
level--;
}
// This script prints the properties of the selected element.
// You should select an element in the DiagramEditor before running this.
run();
function run() {
var targets = getSelectedPresentationsInDiagramEditor();
if (targets.length === 0) {
print('Please select an element in a diagram');
return;
}
for (var i in targets) {
printAllProperties(targets[i]);
}
}
function getSelectedPresentationsInDiagramEditor() {
var diagramViewManager = astah.getViewManager().getDiagramViewManager();
return diagramViewManager.getSelectedPresentations();
}
function printAllProperties(presentation) {
with(new JavaImporter(
java.util)) {
var props = presentation.getProperties();
var keyList = new ArrayList(props.keySet());
Collections.sort(keyList);
print('---------------------------');
for (var i = 0; i < keyList.size(); i++) {
var key = keyList.get(i);
var value = props.get(key);
print(key + ': ' + value);
}
print('---------------------------');
}
}
//This script shows how to check the edition of Astah.
run();
function run() {
if (!isSupportedAstah()) {
print('This edition is not supported');
}
//Use a special API here.
//Ex:
//TransactionManager.beginTransaction();
//Edit the astah model
//TransactionManager.endTransaction();
}
function isSupportedAstah() {
with(new JavaImporter(
com.change_vision.jude.api.inf.editor)) {
var edition = astah.getAstahEdition();
print('Your edition is ' + edition);
if (edition == 'SystemSafety') {
return true;
} else {
return false;
}
}
}
print("AstahVersion : " + astah.getAstahVersion());
print("AstahEdition : " + astah.getAstahEdition());
print("AstahInstallPath : " + astah.getAstahInstallPath());
print("UserHome : " + Java.type('java.lang.System').getProperty('user.home'));
print("AstahModelVersion : " + astah.getAstahModelVersion());
print("AstahAPIVersion : " + astah.getAstahAPIVersion());
print("AstahAPIModelVersion : " + astah.getAstahAPIModelVersion());
//This script shows a GUI by using AWT and Swing of Java.
with(new JavaImporter(
java.awt,
java.awt.event,
javax.swing)) {
var frame = new JFrame("Frame title");
frame.setLayout(new FlowLayout());
var goButton = new JButton("Go!");
goButton.addActionListener(new ActionListener({
actionPerformed: function(event) {
JOptionPane.showMessageDialog(frame, "Hello!");
}
}));
var closeButton = new JButton("Close");
closeButton.addActionListener(new ActionListener({
actionPerformed: function(event) {
frame.setVisible(false);
frame.dispose();
}
}));
frame.add(goButton);
frame.add(closeButton);
frame.setSize(150, 100);
//We must not use JFrame.EXIT_ON_CLOSE
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//We can use 'astahWindow' instead of 'scriptWindow' here.
frame.setLocationRelativeTo(scriptWindow);
frame.setVisible(true);
}
run()
function run() {
with (new JavaImporter(com.change_vision.jude.api.stpa.model)) {
facet = astah.getFacet(IStampFacet.FACET_SYMBOLIC_NAME)
analysis = facet.getRootElement(IStpaAnalysis.class)
components = analysis.getComponents()
controlActions = getControlActions(analysis, components.get(0))
controlActions.forEach(
function(controlAction) {
print('CA: ' + controlAction.getName())
}
)
}
}
function getControlActions(analysis, component) {
with (new JavaImporter(java.util, com.change_vision.jude.api.stpa.model)) {
controlActions = new ArrayList()
links = analysis.getLinks()
links.forEach(
function(link) {
if (link instanceof IControlLink
&& (link.getSource() == component || link.getTarget() == component)) {
controlActions.addAll(link.getActions())
}
}
)
return controlActions
}
}
run()
function run() {
with (new JavaImporter(com.change_vision.jude.api.stpa.model)) {
facet = astah.getFacet(IStampFacet.FACET_SYMBOLIC_NAME)
analysis = facet.getRootElement(IStpaAnalysis.class)
ucas = analysis.getUnsafeControlActions()
uca = ucas.get(0)
hcfs = getHazardCausalFactors(analysis, uca)
if (hcfs.isEmpty()) {
print(uca.getIdentifier() + ' has no HCFs')
} else {
print(uca.getIdentifier() + ' has HCFs')
}
}
}
function getHazardCausalFactors(analysis, uca) {
with (new JavaImporter(java.util)) {
hcfs = new ArrayList()
allHcfs = analysis.getHazardCausalFactors()
allHcfs.forEach(
function(hcf) {
if (hcf.getUnsafeControlAction() == uca) {
hcfs.add(hcf)
}
}
)
return hcfs
}
}
run()
function run() {
with (new JavaImporter(com.change_vision.jude.api.stpa.model)) {
var facet = astah.getFacet(IStampFacet.FACET_SYMBOLIC_NAME);
var analysis = facet.getRootElement(IStpaAnalysis.class);
for (var i in analysis.diagrams) {
var diagram = analysis.diagrams[i]
if (diagram instanceof ILossScenarioTable) {
print(diagram.name);
var hazardCausalFactors = diagram.hazardCausalFactors;
for (var j in hazardCausalFactors) {
var hcf = hazardCausalFactors[j];
print(" [" + hcf.identifier + "] " + hcf.description);
}
}
}
}
}
run()
function run() {
with (new JavaImporter(com.change_vision.jude.api.stpa.model)) {
var facet = astah.getFacet(IStampFacet.FACET_SYMBOLIC_NAME);
var analysis = facet.getRootElement(IStpaAnalysis.class);
for (var i in analysis.diagrams) {
var diagram = analysis.diagrams[i]
if (diagram instanceof ILossScenarioTable) {
var hazardCausalFactors = diagram.hazardCausalFactors;
for (var j in hazardCausalFactors) {
var hcf = hazardCausalFactors[j];
for (var k in hcf.hazardScenarios) {
var scenario = hcf.hazardScenarios[k];
print(scenario.description);
}
}
}
}
}
}
run()
function run() {
with (new JavaImporter(com.change_vision.jude.api.gsn.model)) {
goals = astah.findElements(IGoal.class)
targets = getInContextOfTargets(goals[0])
targets.forEach(
function(target) {
print('Target: ' + target.getIdentifier())
}
)
}
}
function getInContextOfTargets(argumentAsset) {
with (new JavaImporter(java.util, com.change_vision.jude.api.gsn.model)) {
targets = new ArrayList()
facet = astah.getFacet(IGsnFacet.FACET_SYMBOLIC_NAME)
rootElement = facet.getRootElement(IModule.class)
argumentationElements = rootElement.getArgumentationElements()
argumentationElements.forEach(
function(argumentationElement) {
if (argumentationElement instanceof IInContextOf
&& argumentationElement.getSource() == argumentAsset) {
targets.add(argumentationElement.getTarget())
}
}
)
return targets
}
}
run()
function run() {
with (new JavaImporter(java.lang, java.util, com.change_vision.jude.api.gsn.model)) {
goals = astah.findElements(IGoal.class)
goal = goals[0]
solutions = new HashSet()
try {
getSolutions(goal, solutions)
if (solutions.isEmpty()) {
print(goal.getIdentifier() + ' has no Solutions')
} else {
print(goal.getIdentifier() + ' has Solutions')
}
} catch (e) {
if (e instanceof StackOverflowError) {
print('Too many calls. SupportedBy may loop.')
} else {
throw e
}
}
}
}
function getSolutions(goalOrStrategy, solutions) {
with (new JavaImporter(com.change_vision.jude.api.gsn.model)) {
facet = astah.getFacet(IGsnFacet.FACET_SYMBOLIC_NAME)
rootElement = facet.getRootElement(IModule.class)
argumentationElements = rootElement.getArgumentationElements()
argumentationElements.forEach(
function(argumentationElement) {
if (argumentationElement instanceof ISupportedBy
&& argumentationElement.getSource() == goalOrStrategy) {
target = argumentationElement.getTarget()
if (target instanceof ISolution) {
solutions.add(target)
} else if (target instanceof IGoal || target instanceof IStrategy) {
getSolutions(target, solutions)
}
}
}
)
}
}