Skip to content
Draft
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
6 changes: 4 additions & 2 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

- https://github.com/eclipse-syson/syson/issues/2198[#2198] [diagrams] Improve diagram-to-diagram drag and drop to support dropping multiple graphical nodes at once, leveraging Sirius Web's `droppedNodes` and `droppedElements` variables.
- https://github.com/eclipse-syson/syson/issues/2194[#2194] [diagrams] Properly report feedback messages to user when using _ISysMLMoveElementService_.
- https://github.com/eclipse-syson/syson/issues/2182[#2182] [services] Provide a way for downstream applications to extend _ISysMLMoveElementService_;

- https://github.com/eclipse-syson/syson/issues/2182[#2182] [services] Provide a way for downstream applications to extend _ISysMLMoveElementService_.
- https://github.com/eclipse-syson/syson/issues/2119[#2119] [details] Display expressions values in the _Details_ view and allow to edit them from there.

=== New features

Expand All @@ -32,6 +32,8 @@ Disabling the _Hide expression internals_ filter in the _Explorer_ view allows t
- https://github.com/eclipse-syson/syson/issues/2231[#2231] [diagrams] Add a new tool to create a _frame_ `ConcernUsage` from `RequirementUsage` and `RequirementDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2231[#2231] [diagrams] Add the support for the _frames_ compartment graphical node in `RequirementUsage` and `RequirementDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2235[#2235] [diagrams] Leverage the selection dialog to improve the graphical node tool creating a _frame_ `ConcernUsage` from `RequirementUsage` and `RequirementDefinition` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2097[#2097] [explorer] Add support for creating and editing exressions through their textual representation.
This is currently supported on `Features` (e.g. `Attribute`), `Constraints` and `Transitions` (guard conditions) view new context menu actions (_Create expression_ and _Edit expression_) on the corresponding elements in the _Explorer_.

== v2026.5.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.syson.sysml.Element;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory.Descriptor;
import org.eclipse.sirius.components.collaborative.forms.services.api.IPropertiesDescriptionRegistry;
import org.eclipse.sirius.components.collaborative.forms.services.api.IPropertiesDescriptionRegistryConfigurer;
Expand Down Expand Up @@ -63,8 +62,9 @@
import org.eclipse.syson.model.services.ModelMutationElementService;
import org.eclipse.syson.model.services.aql.ModelMutationAQLService;
import org.eclipse.syson.model.services.aql.ModelQueryAQLService;
import org.eclipse.syson.services.UtilService;
import org.eclipse.syson.sysml.Element;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService;
import org.eclipse.syson.util.AQLConstants;
import org.eclipse.syson.util.AQLUtils;
import org.eclipse.syson.util.ServiceMethod;
Expand All @@ -79,6 +79,8 @@
@Configuration
public class SysMLv2PropertiesConfigurer implements IPropertiesDescriptionRegistryConfigurer {

private static final String CUSTOM_EXPRESSION_WIDGET_KEY = "syson:expression-value-widget";

private static final String CORE_PROPERTIES = "Core Properties";

private static final String ADVANCED_PROPERTIES = "Advanced Properties";
Expand Down Expand Up @@ -119,10 +121,10 @@ public class SysMLv2PropertiesConfigurer implements IPropertiesDescriptionRegist

private final ILabelService labelService;

private final UtilService utilService;

private final IReadOnlyObjectPredicate readOnlyObjectPredicate;

private final MetamodelQueryElementService metamodelQueryElementService;

private final List<IDetailsViewHelpTextProvider> detailViewHelpTextProviders;

public SysMLv2PropertiesConfigurer(List<Descriptor> composedAdapterFactoryDescriptors, ViewFormDescriptionConverter converter, IFeedbackMessageService feedbackMessageService,
Expand All @@ -133,7 +135,7 @@ public SysMLv2PropertiesConfigurer(List<Descriptor> composedAdapterFactoryDescri
this.labelService = Objects.requireNonNull(labelService);
this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate);
this.detailViewHelpTextProviders = Objects.requireNonNull(detailViewHelpTextProviders);
this.utilService = new UtilService();
this.metamodelQueryElementService = new MetamodelQueryElementService();
}

@Override
Expand All @@ -155,7 +157,8 @@ public void addPropertiesDescriptions(IPropertiesDescriptionRegistry registry) {

// Convert the View-based FormDescription and register the result into the system
AQLInterpreter interpreter = new AQLInterpreter(List.of(),
List.of(new DetailsViewService(this.composedAdapterFactoryDescriptors, this.feedbackMessageService, this.readOnlyObjectPredicate, this.detailViewHelpTextProviders), this.labelService, this.utilService,
List.of(new DetailsViewService(this.composedAdapterFactoryDescriptors, this.feedbackMessageService, this.readOnlyObjectPredicate, this.metamodelQueryElementService,
this.detailViewHelpTextProviders), this.labelService,
new ModelMutationAQLService(new ModelMutationElementService()), new ModelQueryAQLService(), new FormMutationAQLService(), new FormQueryAQLService()),
List.of(SysmlPackage.eINSTANCE));
ViewConverterResult converterResult = this.converter.convert(viewFormDescription, List.of(), interpreter);
Expand Down Expand Up @@ -188,6 +191,7 @@ private FormDescription createDetailsViewForElement() {
pageCore.getGroups().add(this.createExtraAcceptActionUsagePropertiesGroup());
pageCore.getGroups().add(this.createExtraTransitionSourceTargetPropertiesGroup());
pageCore.getGroups().add(this.createFeatureValuePropertiesGroup());
pageCore.getGroups().add(this.createExpressionPropertiesGroup());

PageDescription pageAdvanced = FormFactory.eINSTANCE.createPageDescription();
pageAdvanced.setName("SysON-DetailsView-Advanced");
Expand All @@ -202,6 +206,28 @@ private FormDescription createDetailsViewForElement() {
return form;
}

/**
* Creates a group to display the value of an Expression.
*
* @return a {@link GroupDescription}
*/
private GroupDescription createExpressionPropertiesGroup() {
GroupDescription group = FormFactory.eINSTANCE.createGroupDescription();
group.setDisplayMode(GroupDisplayMode.LIST);
group.setName("Expression Value");
group.setLabelExpression("");
group.setSemanticCandidatesExpression(ServiceMethod.of0(DetailsViewService::getExpression).aqlSelf());

TextAreaDescription expressionWidget = FormFactory.eINSTANCE.createTextAreaDescription();
expressionWidget.setName("Expression");
expressionWidget.setLabelExpression(CUSTOM_EXPRESSION_WIDGET_KEY);
expressionWidget.setValueExpression(ServiceMethod.of0(DetailsViewService::getExpressionTextualRepresentation).aqlSelf());
expressionWidget.setIsEnabledExpression(AQLConstants.AQL_FALSE);

group.getChildren().add(expressionWidget);

return group;
}

/**
* Creates a group to display the value of a Feature or FeatureValue.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* 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.expressions.dto;

import java.util.UUID;

import org.eclipse.sirius.components.core.api.IInput;

/**
* The input object for the {@code deleteExpression} mutation.
*
* @author pcdavid
*/
public record DeleteExpressionInput(UUID id, String editingContextId, String parentElementId) implements IInput {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* 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.expressions.dto;

import java.util.UUID;

import org.eclipse.sirius.components.core.api.IInput;

/**
* Input for the {@code expressionTextualRepresentation} query field on EditingContext.
*
* @author pcdavid
*/
public record ExpressionTextualRepresentationInput(UUID id, String editingContextId, String elementId) implements IInput {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*******************************************************************************
* 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.expressions.dto;

import java.util.Objects;
import java.util.UUID;

import org.eclipse.sirius.components.core.api.IPayload;

/**
* Payload for the {@code expressionTextualRepresentation} query field on EditingContext.
*
* @author pcdavid
*/
public record ExpressionTextualRepresentationPayload(UUID id, String textualRepresentation) implements IPayload {
public ExpressionTextualRepresentationPayload {
Objects.requireNonNull(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* 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.expressions.graphql;

import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

import org.eclipse.sirius.components.annotations.spring.graphql.QueryDataFetcher;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher;
import org.eclipse.syson.application.expressions.dto.ExpressionTextualRepresentationInput;
import org.eclipse.syson.application.expressions.dto.ExpressionTextualRepresentationPayload;

import graphql.schema.DataFetchingEnvironment;

/**
* Data fetcher for the field {@code EditingContext#expressionTextualRepresentation} to fetch the textual representation
* of a SysMLv2 expression.
*
* @author pcdavid
*/
@QueryDataFetcher(type = "EditingContext", field = "expressionTextualRepresentation")
public class EditingContextExpressionTextualRepresentationDataFetcher implements IDataFetcherWithFieldCoordinates<CompletableFuture<String>> {

private static final String ELEMENT_ID_ARGUMENT = "elementId";

private final IEditingContextDispatcher editingContextDispatcher;

public EditingContextExpressionTextualRepresentationDataFetcher(IEditingContextDispatcher editingContextDispatcher) {
this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher);
}

@Override
public CompletableFuture<String> get(DataFetchingEnvironment environment) throws Exception {
String editingContextId = environment.getSource();
String elementId = environment.getArgument(ELEMENT_ID_ARGUMENT);

ExpressionTextualRepresentationInput input = new ExpressionTextualRepresentationInput(UUID.randomUUID(), editingContextId, elementId);
return this.editingContextDispatcher.dispatchQuery(input.editingContextId(), input)
.filter(ExpressionTextualRepresentationPayload.class::isInstance)
.map(ExpressionTextualRepresentationPayload.class::cast)
.map(ExpressionTextualRepresentationPayload::textualRepresentation)
.toFuture();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*******************************************************************************
* 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.expressions.graphql;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;

import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher;
import org.eclipse.sirius.components.graphql.api.IExceptionWrapper;
import org.eclipse.syson.application.expressions.dto.DeleteExpressionInput;

import graphql.schema.DataFetchingEnvironment;
import tools.jackson.databind.ObjectMapper;

/**
* The GraphQL data-fetcher for the {@code deleteExpression} mutation to delete the expression associated to a SysMLv2
* element.
*
* @author pcdavid
*/
@MutationDataFetcher(type = "Mutation", field = "deleteExpression")
public class MutationDeleteExpressionDataFetcher implements IDataFetcherWithFieldCoordinates<CompletableFuture<IPayload>> {

private static final String INPUT_ARGUMENT = "input";

private final ObjectMapper objectMapper;

private final IExceptionWrapper exceptionWrapper;

private final IEditingContextDispatcher editingContextDispatcher;

public MutationDeleteExpressionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) {
this.objectMapper = Objects.requireNonNull(objectMapper);
this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper);
this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher);
}

@Override
public CompletableFuture<IPayload> get(DataFetchingEnvironment environment) throws Exception {
Object argument = environment.getArgument(INPUT_ARGUMENT);
var input = this.objectMapper.convertValue(argument, DeleteExpressionInput.class);
return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture();
}
}
Loading
Loading