Created
January 29, 2026 13:59
-
-
Save romualdrichard/b0e9f3198207e6b8be65a6698787864c to your computer and use it in GitHub Desktop.
#jarchi create a view from a criteria
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * JArchi Script - Search and Create View | |
| * Search for model elements by text and create a view with the results | |
| */ | |
| // Import necessary SWT classes | |
| var SWT = Java.type('org.eclipse.swt.SWT'); | |
| var Shell = Java.type('org.eclipse.swt.widgets.Shell'); | |
| var Display = Java.type('org.eclipse.swt.widgets.Display'); | |
| var Dialog = Java.type('org.eclipse.swt.widgets.Dialog'); | |
| var Label = Java.type('org.eclipse.swt.widgets.Label'); | |
| var Text = Java.type('org.eclipse.swt.widgets.Text'); | |
| var Button = Java.type('org.eclipse.swt.widgets.Button'); | |
| var Combo = Java.type('org.eclipse.swt.widgets.Combo'); | |
| var GridLayout = Java.type('org.eclipse.swt.layout.GridLayout'); | |
| var GridData = Java.type('org.eclipse.swt.layout.GridData'); | |
| var SelectionAdapter = Java.type('org.eclipse.swt.events.SelectionAdapter'); | |
| // Class for the search dialog box | |
| function SearchDialog(parentShell) { | |
| this.searchText = ""; | |
| this.scope = "all"; // all, elements, relations | |
| this.searchInName = true; | |
| this.searchInDocumentation = true; | |
| this.searchInProperties = true; | |
| this.cancelled = true; | |
| this.open = function() { | |
| var display = parentShell ? parentShell.getDisplay() : Display.getDefault(); | |
| var shell = new Shell(parentShell, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL); | |
| shell.setText("Search ArchiMate Elements"); | |
| shell.setSize(500, 300); | |
| var layout = new GridLayout(2, false); | |
| shell.setLayout(layout); | |
| // Label and text field for search | |
| var labelSearch = new Label(shell, SWT.NONE); | |
| labelSearch.setText("Search text:"); | |
| var textSearch = new Text(shell, SWT.BORDER); | |
| var gdText = new GridData(SWT.FILL, SWT.CENTER, true, false); | |
| textSearch.setLayoutData(gdText); | |
| // Label and combo for scope | |
| var labelScope = new Label(shell, SWT.NONE); | |
| labelScope.setText("Search scope:"); | |
| var comboScope = new Combo(shell, SWT.READ_ONLY); | |
| comboScope.setItems(["All model", "Elements only", "Relations only"]); | |
| comboScope.select(0); | |
| var gdCombo = new GridData(SWT.FILL, SWT.CENTER, true, false); | |
| comboScope.setLayoutData(gdCombo); | |
| // Label for search criteria | |
| var labelCriteria = new Label(shell, SWT.NONE); | |
| labelCriteria.setText("Search in:"); | |
| var gdLabelCriteria = new GridData(SWT.LEFT, SWT.TOP, false, false); | |
| labelCriteria.setLayoutData(gdLabelCriteria); | |
| // Composite for checkboxes | |
| var checkboxComposite = new Shell(shell, SWT.NONE); | |
| var checkboxLayout = new GridLayout(1, false); | |
| checkboxComposite.setLayout(checkboxLayout); | |
| var gdCheckboxComposite = new GridData(SWT.FILL, SWT.FILL, true, false); | |
| checkboxComposite.setLayoutData(gdCheckboxComposite); | |
| var checkName = new Button(shell, SWT.CHECK); | |
| checkName.setText("Name"); | |
| checkName.setSelection(true); | |
| var gdCheckName = new GridData(SWT.FILL, SWT.CENTER, true, false); | |
| checkName.setLayoutData(gdCheckName); | |
| var checkDoc = new Button(shell, SWT.CHECK); | |
| checkDoc.setText("Documentation"); | |
| checkDoc.setSelection(true); | |
| var gdCheckDoc = new GridData(SWT.FILL, SWT.CENTER, true, false); | |
| checkDoc.setLayoutData(gdCheckDoc); | |
| var checkProps = new Button(shell, SWT.CHECK); | |
| checkProps.setText("Properties"); | |
| checkProps.setSelection(true); | |
| var gdCheckProps = new GridData(SWT.FILL, SWT.CENTER, true, false); | |
| checkProps.setLayoutData(gdCheckProps); | |
| // OK and Cancel buttons | |
| var buttonComposite = new Shell(shell, SWT.NONE); | |
| var buttonLayout = new GridLayout(2, true); | |
| buttonComposite.setLayout(buttonLayout); | |
| var gdButtons = new GridData(SWT.RIGHT, SWT.CENTER, true, false); | |
| gdButtons.horizontalSpan = 2; | |
| buttonComposite.setLayoutData(gdButtons); | |
| var btnOK = new Button(shell, SWT.PUSH); | |
| btnOK.setText("OK"); | |
| var gdOK = new GridData(SWT.RIGHT, SWT.CENTER, false, false); | |
| gdOK.widthHint = 80; | |
| gdOK.horizontalSpan = 1; | |
| btnOK.setLayoutData(gdOK); | |
| var btnCancel = new Button(shell, SWT.PUSH); | |
| btnCancel.setText("Cancel"); | |
| var gdCancel = new GridData(SWT.RIGHT, SWT.CENTER, false, false); | |
| gdCancel.widthHint = 80; | |
| btnCancel.setLayoutData(gdCancel); | |
| var self = this; | |
| // Handle OK button | |
| btnOK.addSelectionListener(new SelectionAdapter() { | |
| widgetSelected: function(e) { | |
| self.searchText = textSearch.getText(); | |
| var scopeIndex = comboScope.getSelectionIndex(); | |
| if (scopeIndex === 0) self.scope = "all"; | |
| else if (scopeIndex === 1) self.scope = "elements"; | |
| else if (scopeIndex === 2) self.scope = "relations"; | |
| self.searchInName = checkName.getSelection(); | |
| self.searchInDocumentation = checkDoc.getSelection(); | |
| self.searchInProperties = checkProps.getSelection(); | |
| // Verify that at least one criterion is selected | |
| if (!self.searchInName && !self.searchInDocumentation && !self.searchInProperties) { | |
| window.alert("Please select at least one search criterion!"); | |
| return; | |
| } | |
| self.cancelled = false; | |
| shell.close(); | |
| } | |
| }); | |
| // Handle Cancel button | |
| btnCancel.addSelectionListener(new SelectionAdapter() { | |
| widgetSelected: function(e) { | |
| self.cancelled = true; | |
| shell.close(); | |
| } | |
| }); | |
| // Center the window | |
| var parentBounds = parentShell ? parentShell.getBounds() : display.getPrimaryMonitor().getBounds(); | |
| var shellBounds = shell.getBounds(); | |
| var x = parentBounds.x + (parentBounds.width - shellBounds.width) / 2; | |
| var y = parentBounds.y + (parentBounds.height - shellBounds.height) / 2; | |
| shell.setLocation(x, y); | |
| shell.open(); | |
| while (!shell.isDisposed()) { | |
| if (!display.readAndDispatch()) { | |
| display.sleep(); | |
| } | |
| } | |
| return !this.cancelled; | |
| }; | |
| } | |
| // Function to search for text in an element | |
| function matchesSearch(element, searchText, searchInName, searchInDocumentation, searchInProperties) { | |
| if (!searchText || searchText.trim() === "") { | |
| return true; | |
| } | |
| var search = searchText.toLowerCase(); | |
| // Search in name | |
| if (searchInName && element.name && element.name.toLowerCase().indexOf(search) !== -1) { | |
| return true; | |
| } | |
| // Search in documentation | |
| if (searchInDocumentation && element.documentation && element.documentation.toLowerCase().indexOf(search) !== -1) { | |
| return true; | |
| } | |
| // Search in properties | |
| if (searchInProperties && element.prop) { | |
| var props = element.prop(); | |
| for (var i = 0; i < props.length; i++) { | |
| var key = props[i]; | |
| var value = element.prop(key); | |
| if (key.toLowerCase().indexOf(search) !== -1 || | |
| (value && value.toLowerCase().indexOf(search) !== -1)) { | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| // Main function | |
| function main() { | |
| // Check that a model is open | |
| if (!model) { | |
| window.alert("No model is open!"); | |
| return; | |
| } | |
| // Display the dialog box | |
| var dialog = new SearchDialog(shell); | |
| if (!dialog.open()) { | |
| console.log("Search cancelled by user"); | |
| return; | |
| } | |
| var searchText = dialog.searchText; | |
| var scope = dialog.scope; | |
| var searchInName = dialog.searchInName; | |
| var searchInDocumentation = dialog.searchInDocumentation; | |
| var searchInProperties = dialog.searchInProperties; | |
| console.log("Search: '" + searchText + "' in scope: " + scope); | |
| console.log("Search in - Name: " + searchInName + ", Documentation: " + searchInDocumentation + ", Properties: " + searchInProperties); | |
| // Collections to store results | |
| var foundElements = []; | |
| var foundRelations = []; | |
| var elementsToDisplay = {}; // Map to avoid duplicates | |
| // Search in elements | |
| if (scope === "all" || scope === "elements") { | |
| $("element").each(function(element) { | |
| if (matchesSearch(element, searchText, searchInName, searchInDocumentation, searchInProperties)) { | |
| foundElements.push(element); | |
| elementsToDisplay[element.id] = element; | |
| } | |
| }); | |
| } | |
| // Search in relations | |
| if (scope === "all" || scope === "relations") { | |
| $("relationship").each(function(relation) { | |
| if (matchesSearch(relation, searchText, searchInName, searchInDocumentation, searchInProperties)) { | |
| foundRelations.push(relation); | |
| // Add source and target of found relations | |
| if (relation.source) { | |
| elementsToDisplay[relation.source.id] = relation.source; | |
| } | |
| if (relation.target) { | |
| elementsToDisplay[relation.target.id] = relation.target; | |
| } | |
| } | |
| }); | |
| } | |
| // Remove duplicates in relations | |
| var uniqueRelations = []; | |
| var relationIds = {}; | |
| foundRelations.forEach(function(rel) { | |
| if (!relationIds[rel.id]) { | |
| uniqueRelations.push(rel); | |
| relationIds[rel.id] = true; | |
| } | |
| }); | |
| console.log("Elements found: " + foundElements.length); | |
| console.log("Relations found: " + uniqueRelations.length); | |
| console.log("Total elements to display: " + Object.keys(elementsToDisplay).length); | |
| // Check if there are results | |
| if (Object.keys(elementsToDisplay).length === 0 && uniqueRelations.length === 0) { | |
| window.alert("No results found for '" + searchText + "'"); | |
| return; | |
| } | |
| // Create a new view | |
| var scopeLabel = ""; | |
| if (scope === "all") scopeLabel = "All"; | |
| else if (scope === "elements") scopeLabel = "Elements"; | |
| else if (scope === "relations") scopeLabel = "Relations"; | |
| var viewName = "Search [" + scopeLabel + "]: " + searchText; | |
| var view = model.createArchimateView(viewName); | |
| // Add elements to the view | |
| var visualElements = {}; | |
| var x = 50, y = 50; | |
| var spacing = 150; | |
| var elementsPerRow = 5; | |
| var count = 0; | |
| for (var id in elementsToDisplay) { | |
| var element = elementsToDisplay[id]; | |
| var visualElement = view.add(element, x, y, -1, -1); | |
| visualElements[id] = visualElement; | |
| count++; | |
| if (count % elementsPerRow === 0) { | |
| x = 50; | |
| y += spacing; | |
| } else { | |
| x += spacing; | |
| } | |
| } | |
| // Add relations to the view | |
| uniqueRelations.forEach(function(relation) { | |
| if (visualElements[relation.source.id] && visualElements[relation.target.id]) { | |
| view.add(relation, visualElements[relation.source.id], visualElements[relation.target.id]); | |
| } | |
| }); | |
| // Apply automatic layout | |
| view.openInUI(); | |
| var message = "View created successfully!\n\n" + | |
| "Elements: " + Object.keys(elementsToDisplay).length + "\n" + | |
| "Relations: " + uniqueRelations.length; | |
| window.alert(message); | |
| } | |
| // Run the script | |
| main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment