Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Also use that same tool in the `interconnection` compartment.
- https://github.com/eclipse-syson/syson/issues/2166[#2166] [diagrams] Reorganize tools to create `ExhibitStateUsage` graphical nodes, to ends up with two tools, one for parallel, one for non-parallel.
Both tools optionally allow selecting an existing `StateUsage` to exhibit.
- https://github.com/eclipse-syson/syson/issues/2179[#2179] [diagrams] Improve selection dialog by regrouping all standard libraries candidates under a "Libraries" category.
- https://github.com/eclipse-syson/syson/issues/2116[#2116] [explorer] In the _Explorer_ view, the items corresponding to the internals of `Expression` elements (syntax tree) are now hidden by default.
Disabling the _Hide expression internals_ filter in the _Explorer_ view allows to display them if needed.

=== New features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.eclipse.syson.application.controller.explorer.testers.TreeItemContextMenuTester;
import org.eclipse.syson.application.controller.explorer.testers.TreePathTester;
import org.eclipse.syson.application.data.ActionTransitionUsagesProjectData;
import org.eclipse.syson.application.data.ExpressionSamplesProjectData;
import org.eclipse.syson.application.data.GeneralViewEmptyTestProjectData;
import org.eclipse.syson.application.data.ProjectWithLibraryDependencyContainingCommentAndLibraryPackageTestProjectData;
import org.eclipse.syson.application.data.ProjectWithLibraryDependencyContainingLibraryPackageTestProjectData;
Expand Down Expand Up @@ -871,4 +872,128 @@ public void sysONExplorerTreeExpressionLabelTest() {
.thenCancel()
.verify(Duration.ofSeconds(10));
}

@DisplayName("GIVEN the SysON Explorer, WHEN displaying an Expression item, THEN its internal details are hidden by default")
@GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH })
@Test
public void sysONExplorerHidesExpressionInternalsByDefault() {
List<String> defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(ExpressionSamplesProjectData.EDITING_CONTEXT_ID, this.sysONExplorerTreeDescriptionId);

var expandedItemIds = List.of(
ExpressionSamplesProjectData.SemanticIds.EXPRESSIONS_DOCUMENT_ID,
ExpressionSamplesProjectData.SemanticIds.EXPRESSIONS_PACKAGE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_VALUE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_LIMIT_CONSTRAINT_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_LIMIT_CONSTRAINT_VALUE_ID);

var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, expandedItemIds, defaultFilters);
var input = new ExplorerEventInput(UUID.randomUUID(), ExpressionSamplesProjectData.EDITING_CONTEXT_ID, explorerRepresentationId);
var flux = this.explorerEventSubscriptionRunner.run(input).flux();
TestTransaction.flagForCommit();
TestTransaction.end();

var treeId = new AtomicReference<String>();
Consumer<Object> initialTreeContentConsumer = assertRefreshedTreeThat(tree -> {
assertThat(tree).isNotNull();
treeId.set(tree.getId());
assertThat(tree.getChildren()).hasSize(2);
var documentItem = tree.getChildren().get(0);
assertThat(documentItem.getChildren()).hasSize(1);
assertThat(documentItem.getLabel().toString()).isEqualTo("expressions.sysml");
var packageItem = documentItem.getChildren().get(0);
assertThat(packageItem.getLabel().toString()).isEqualTo("Expressions");

assertThat(packageItem.getChildren()).hasSize(7);

var tankItem = this.getChildByLabel(packageItem, "Tank");
assertThat(tankItem).isPresent();

var maxVolumeAttribute = this.getChildByLabel(tankItem.get(), "maxVolume");
assertThat(maxVolumeAttribute).isPresent();
assertThat(maxVolumeAttribute.get().getChildren()).hasSize(2);
var maxVolumeAttributeValueItem = maxVolumeAttribute.get().getChildren().get(0);
assertThat(maxVolumeAttributeValueItem.getLabel().toString()).isEqualTo("100.0 * minVolume");
assertThat(maxVolumeAttributeValueItem.getChildren()).isEmpty(); // Details filtered out by default

var pressureLimitAttribute = this.getChildByLabel(tankItem.get(), "pressureLimit");
assertThat(pressureLimitAttribute).isPresent();
assertThat(pressureLimitAttribute.get().getChildren()).hasSize(1);
var pressureLimitAttributeValueItem = pressureLimitAttribute.get().getChildren().get(0);
assertThat(pressureLimitAttributeValueItem.getLabel().toString()).isEqualTo("pressure <= maxPressure");
assertThat(pressureLimitAttributeValueItem.getChildren()).isEmpty(); // Details filtered out by default

});

StepVerifier.create(flux)
.consumeNextWith(initialTreeContentConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

@DisplayName("GIVEN the SysON Explorer, WHEN displaying an Expression item, THEN its internal details can be revealed by disabling the corresponding filter")
@GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH })
@Test
public void sysONExplorerExpressionInternalsCanBeRevealed() {
List<String> defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(ExpressionSamplesProjectData.EDITING_CONTEXT_ID, this.sysONExplorerTreeDescriptionId);
// Keep all defaults but HIDE_EXPRESSION_INTERNALS_ID
List<String> activeFilters = defaultFilters.stream().filter(filterId -> !SysONTreeFilterConstants.HIDE_EXPRESSION_INTERNALS_ID.equals(filterId)).toList();

var expandedItemIds = List.of(
ExpressionSamplesProjectData.SemanticIds.EXPRESSIONS_DOCUMENT_ID,
ExpressionSamplesProjectData.SemanticIds.EXPRESSIONS_PACKAGE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_VALUE_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_LIMIT_CONSTRAINT_ID,
ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_LIMIT_CONSTRAINT_VALUE_ID);

var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, expandedItemIds, activeFilters);
var input = new ExplorerEventInput(UUID.randomUUID(), ExpressionSamplesProjectData.EDITING_CONTEXT_ID, explorerRepresentationId);
var flux = this.explorerEventSubscriptionRunner.run(input).flux();
TestTransaction.flagForCommit();
TestTransaction.end();

var treeId = new AtomicReference<String>();
Consumer<Object> initialTreeContentConsumer = assertRefreshedTreeThat(tree -> {
assertThat(tree).isNotNull();
treeId.set(tree.getId());
assertThat(tree.getChildren()).hasSize(2);
var documentItem = tree.getChildren().get(0);
assertThat(documentItem.getChildren()).hasSize(1);
assertThat(documentItem.getLabel().toString()).isEqualTo("expressions.sysml");
var packageItem = documentItem.getChildren().get(0);
assertThat(packageItem.getLabel().toString()).isEqualTo("Expressions");

assertThat(packageItem.getChildren()).hasSize(7);

var tankItem = this.getChildByLabel(packageItem, "Tank");
assertThat(tankItem).isPresent();

var maxVolumeAttribute = this.getChildByLabel(tankItem.get(), "maxVolume");
assertThat(maxVolumeAttribute).isPresent();
assertThat(maxVolumeAttribute.get().getChildren()).hasSize(2);
var maxVolumeAttributeValueItem = maxVolumeAttribute.get().getChildren().get(0);
assertThat(maxVolumeAttributeValueItem.getLabel().toString()).isEqualTo("100.0 * minVolume");
assertThat(maxVolumeAttributeValueItem.getChildren()).hasSize(2); // Details visible

var pressureLimitAttribute = this.getChildByLabel(tankItem.get(), "pressureLimit");
assertThat(pressureLimitAttribute).isPresent();
assertThat(pressureLimitAttribute.get().getChildren()).hasSize(1);
var pressureLimitAttributeValueItem = pressureLimitAttribute.get().getChildren().get(0);
assertThat(pressureLimitAttributeValueItem.getLabel().toString()).isEqualTo("pressure <= maxPressure");
assertThat(pressureLimitAttributeValueItem.getChildren()).hasSize(2); // Details visible

});

StepVerifier.create(flux)
.consumeNextWith(initialTreeContentConsumer)
.thenCancel()
.verify(Duration.ofSeconds(10));
}

private Optional<TreeItem> getChildByLabel(TreeItem parent, String label) {
return parent.getChildren().stream().filter(child -> child.getLabel().toString().equals(label)).findFirst();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ public void testSysONFiltersOnSysONExplorer() {
SysONTreeFilterConstants.HIDE_SYSML_STANDARD_LIBRARIES_TREE_FILTER_ID,
SysONTreeFilterConstants.HIDE_USER_LIBRARIES_TREE_FILTER_ID,
SysONTreeFilterConstants.HIDE_ROOT_NAMESPACES_ID,
SysONTreeFilterConstants.HIDE_EXPOSE_ELEMENTS_TREE_ITEM_FILTER_ID);
SysONTreeFilterConstants.HIDE_EXPOSE_ELEMENTS_TREE_ITEM_FILTER_ID,
SysONTreeFilterConstants.HIDE_EXPRESSION_INTERNALS_ID);
}

@DisplayName("GIVEN the Sirius Explorer View, WHEN querying the filters, THEN no syson filters are returned")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.application.data;

/**
* Ids for project "Expression-Samples".
*
* @author pcdavid
*/
public class ExpressionSamplesProjectData {
public static final String EDITING_CONTEXT_ID = "aac82b89-8d53-4b16-91b4-deccc180ba62";

public static final String SCRIPT_PATH = "/scripts/database-content/ExpressionSamples.sql";

/**
* Ids of the semantic elements.
*/
public static final class SemanticIds {
public static final String EXPRESSIONS_DOCUMENT_ID = "ef3e6929-0415-4295-b42f-64bed8bd4f55";

public static final String EXPRESSIONS_PACKAGE_ID = "baf5ea6a-7861-4b92-8be2-3fe7a2ebc415";

public static final String TANK_ID = "2bde22f7-a834-4afa-84bf-1bae1bb434d8";

public static final String TANK_MAX_VOLUME_ATTRIBUTE_ID = "d9926727-7378-4177-a940-2fb6c1c89dce";

public static final String TANK_MAX_VOLUME_ATTRIBUTE_VALUE_ID = "a9216e54-f44c-4b1f-b262-13650324d325";

public static final String TANK_PRESSURE_LIMIT_CONSTRAINT_ID = "7d42ee06-3c27-4eaa-9438-344fc789906a";

public static final String TANK_PRESSURE_LIMIT_CONSTRAINT_VALUE_ID = "faa3b115-5b07-4ecf-9147-0d58ceffaf9c";

}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.function.Predicate;

import org.eclipse.syson.sysml.ActorMembership;
import org.eclipse.syson.sysml.BooleanExpression;
import org.eclipse.syson.sysml.Connector;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.Expression;
Expand Down Expand Up @@ -80,16 +81,41 @@ public boolean isStakeholder(Element element) {
}

/**
* Check if a given {@code element} is an {@link Expression} definition. We can not simply rely on whether the
* element is an instance of {@link Expression} as many types in SysMLv2 inherit from this type without being
* themselves an actual expressions.
* Check if a given {@link Element element} is an {@link Expression expression} definition. We can not simply rely
* on whether the element is an instance of {@link Expression expression} as many types in SysMLv2 inherit from this
* type without being themselves an actual expressions.
*
* @param element
* the element to test.
* @return true if the element is an actual expression definition.
*/
public boolean isExpressionDefinition(Element element) {
return element instanceof Expression && !(element instanceof Usage);
return element instanceof Expression && !(element instanceof Usage) && !(element instanceof BooleanExpression);
}

/**
* Check is a given {@link Element element} is a top-level {@link Expression expression}. In most cases, end-users
* are only interested with these and not the internal elements which are technically also expressions but represent
* parts of the overall expression.
*
* @param element
* the element to test.
* @return true if the element is a top-level expression definition.
*/
public boolean isTopLevelExpression(Element element) {
boolean result = false;
if (this.isExpressionDefinition(element)) {
result = true;
var ancestor = element.getOwner();
while (ancestor != null) {
if (this.isExpressionDefinition(ancestor)) {
result = false;
break;
}
ancestor = ancestor.getOwner();
}
}
return result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.tree.explorer.filters;

import java.util.List;
import java.util.Objects;

import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.web.application.views.explorer.services.api.IExplorerTreeItemAlteredContentProvider;
import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerFilterService;
import org.springframework.stereotype.Service;

/**
* An implementation of {@link IExplorerTreeItemAlteredContentProvider} allowing to hide internal elements of
* expressions from Explorer tree.
*
* @author pcdavid
*/
@Service
public class HideExpressionInternalsTreeItemAlteredContentProvider implements IExplorerTreeItemAlteredContentProvider {

private final ISysONExplorerFilterService filterService;

public HideExpressionInternalsTreeItemAlteredContentProvider(ISysONExplorerFilterService filterService) {
this.filterService = Objects.requireNonNull(filterService);
}

@Override
public boolean canHandle(Object object, List<String> activeFilterIds) {
return activeFilterIds.contains(SysONTreeFilterConstants.HIDE_EXPRESSION_INTERNALS_ID);
}

@Override
public List<Object> apply(List<Object> computedChildren, VariableManager variableManager) {
return this.filterService.hideExpressionInternals(computedChildren);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,6 @@ public class SysONTreeFilterConstants {
public static final String HIDE_ROOT_NAMESPACES_ID = UUID.nameUUIDFromBytes("SysONTreeRootNamespacesFilter".getBytes()).toString();

public static final String HIDE_EXPOSE_ELEMENTS_TREE_ITEM_FILTER_ID = UUID.nameUUIDFromBytes("SysONTreeExposeElementsFilter".getBytes()).toString();

public static final String HIDE_EXPRESSION_INTERNALS_ID = UUID.nameUUIDFromBytes("SysONTreeExpressionInternalsFilter".getBytes()).toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.services.api.ISysONResourceService;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.Expose;
import org.eclipse.syson.sysml.LibraryPackage;
import org.eclipse.syson.sysml.Membership;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService;
import org.eclipse.syson.sysml.util.ElementUtil;
import org.eclipse.syson.tree.explorer.filters.SysONTreeFilterConstants;
import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerFilterService;
Expand All @@ -41,8 +43,11 @@ public class SysONExplorerFilterService implements ISysONExplorerFilterService {

private final ISysONResourceService sysONResourceService;

private final MetamodelQueryElementService metamodelQueryElementService;

public SysONExplorerFilterService(final ISysONResourceService sysONResourceService) {
this.sysONResourceService = Objects.requireNonNull(sysONResourceService);
this.metamodelQueryElementService = new MetamodelQueryElementService();
}

@Override
Expand Down Expand Up @@ -127,6 +132,17 @@ public List<Object> hideExposeElements(List<Object> elements) {
.toList();
}

@Override
public List<Object> hideExpressionInternals(List<Object> elements) {
return elements.stream().filter(e -> {
boolean isExpressionInternalElement = false;
if (e instanceof Element element && !this.metamodelQueryElementService.isTopLevelExpression(element)) {
isExpressionInternalElement = element.getOwner() != null && this.metamodelQueryElementService.isTopLevelExpression(element.getOwner());
}
return !isExpressionInternalElement;
}).toList();
}

@Override
public List<Object> applyFilters(IEditingContext editingContext, List<?> elements, List<String> activeFilterIds) {
List<Object> alteredElements = new ArrayList<>(elements);
Expand All @@ -148,6 +164,9 @@ public List<Object> applyFilters(IEditingContext editingContext, List<?> element
if (activeFilterIds.contains(SysONTreeFilterConstants.HIDE_EXPOSE_ELEMENTS_TREE_ITEM_FILTER_ID)) {
alteredElements = this.hideExposeElements(alteredElements);
}
if (activeFilterIds.contains(SysONTreeFilterConstants.HIDE_EXPRESSION_INTERNALS_ID)) {
alteredElements = this.hideExpressionInternals(alteredElements);
}
return alteredElements;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024, 2025 Obeo.
* Copyright (c) 2024, 2026 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand Down Expand Up @@ -41,6 +41,8 @@ public interface ISysONExplorerFilterService {

List<Object> hideExposeElements(List<Object> elements);

List<Object> hideExpressionInternals(List<Object> elements);

List<Object> applyFilters(IEditingContext editingContext, List<?> elements, List<String> activeFilterIds);

}
Loading
Loading