From 3e7f13d0e057841d67016ab6f554826a06f89ec4 Mon Sep 17 00:00:00 2001 From: Pierre-Charles David Date: Tue, 19 May 2026 17:21:27 +0200 Subject: [PATCH] [2097] Handle expressions in SysON Bug: https://github.com/eclipse-syson/syson/issues/2097 Signed-off-by: Pierre-Charles David --- CHANGELOG.adoc | 2 + .../SysMLv2PropertiesConfigurer.java | 13 +- .../dto/DeleteExpressionInput.java | 25 + .../ExpressionTextualRepresentationInput.java | 25 + ...xpressionTextualRepresentationPayload.java | 29 + ...ssionTextualRepresentationDataFetcher.java | 56 ++ .../MutationDeleteExpressionDataFetcher.java | 57 ++ .../DeleteExpressionEventHandler.java | 86 +++ ...sionTextualRepresentationEventHandler.java | 68 ++ .../services/DetailsViewService.java | 69 +- .../resources/schema/expressions.graphqls | 15 + .../services/DetailsViewServiceTest.java | 3 +- .../explorer/view/SysONExplorerTests.java | 24 +- ...xpressionsControllersIntegrationTests.java | 649 ++++++++++++++++++ .../CreateExpressionMutationRunner.java | 62 ++ .../DeleteExpressionMutationRunner.java | 61 ++ .../graphql/EditExpressionMutationRunner.java | 62 ++ ...ssionTextualRepresentationQueryRunner.java | 50 ++ .../data/ExpressionSamplesProjectData.java | 37 + .../database-content/ExpressionSamples.sql | 2 +- .../eclipse/syson/sysml/ASTTransformer.java | 105 ++- .../MutationCreateExpressionDataFetcher.java | 56 ++ .../MutationEditExpressionDataFetcher.java | 56 ++ .../sysml/dto/CreateExpressionInput.java | 25 + .../dto/CreateExpressionSuccessPayload.java | 33 + .../syson/sysml/dto/EditExpressionInput.java | 25 + .../dto/EditExpressionSuccessPayload.java | 33 + .../CreateExpressionEventHandler.java | 113 +++ .../services/EditExpressionEventHandler.java | 111 +++ .../InsertTextualSysMLv2EventHandler.java | 72 +- .../services/SysideExpressionEditor.java | 201 ++++++ .../services/SysideSysMLTextImporter.java | 72 ++ .../api/ExpressionCreationResult.java | 27 + .../services/api/ISysMLExpressionEditor.java | 29 + .../services/api/ISysMLTextImporter.java | 28 + .../resources/schema/syson-import.graphqls | 36 +- .../impl/ResultExpressionMembershipImpl.java | 13 +- .../MetamodelQueryElementService.java | 93 +++ .../SysONDefaultExplorerServices.java | 28 +- ...lorerTreeItemContextMenuEntryProvider.java | 76 +- .../images/edit-expression-modal-error.png | Bin 0 -> 70881 bytes .../assets/images/edit-expression-modal.png | Bin 0 -> 38663 bytes .../images/explorer-expression-full-text.png | Bin 0 -> 39582 bytes .../pages/features/diagramming-tools.adoc | 1 + .../pages/features/expressions.adoc | 51 ++ .../pages/release-notes/2026.7.0.adoc | 15 + .../user-manual/partials/nav-features.adoc | 1 + .../user-manual/partials/nav-howtos.adoc | 1 + .../modules/user-manual/partials/nav-ui.adoc | 1 + .../NewObjectAsTextDocumentReport.tsx | 2 +- .../SysONExtensionRegistryMergeStrategy.ts | 2 +- .../DeleteSysMLExpressionMenuContribution.tsx | 59 ++ .../EditSysMLExpressionMenuContribution.tsx | 68 ++ .../expressions/EditSysMLExpressionModal.tsx | 319 +++++++++ .../EditSysMLExpressionModal.types.ts | 31 + .../NewSysMLExpressionMenuContribution.tsx | 68 ++ .../expressions/useCreateExpression.ts | 84 +++ .../expressions/useCreateExpression.types.ts | 46 ++ .../expressions/useDeleteExpression.ts | 71 ++ .../expressions/useDeleteExpression.types.ts | 42 ++ .../expressions/useEditExpression.ts | 86 +++ .../expressions/useEditExpression.types.ts | 47 ++ .../useExpressionTextualRepresentation.ts | 56 ++ ...seExpressionTextualRepresentation.types.ts | 34 + .../registry/SysONExtensionRegistry.ts | 22 +- 65 files changed, 3555 insertions(+), 179 deletions(-) create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/DeleteExpressionInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationPayload.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/EditingContextExpressionTextualRepresentationDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/MutationDeleteExpressionDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/DeleteExpressionEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/ExpressionTextualRepresentationEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/resources/schema/expressions.graphqls create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/ExpressionsControllersIntegrationTests.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/CreateExpressionMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/DeleteExpressionMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/EditExpressionMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/ExpressionTextualRepresentationQueryRunner.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationCreateExpressionDataFetcher.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationEditExpressionDataFetcher.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionInput.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionSuccessPayload.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionInput.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionSuccessPayload.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/CreateExpressionEventHandler.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/EditExpressionEventHandler.java rename backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/{dto => services}/InsertTextualSysMLv2EventHandler.java (60%) create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideExpressionEditor.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideSysMLTextImporter.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ExpressionCreationResult.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLExpressionEditor.java create mode 100644 backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLTextImporter.java create mode 100644 doc/content/modules/user-manual/assets/images/edit-expression-modal-error.png create mode 100644 doc/content/modules/user-manual/assets/images/edit-expression-modal.png create mode 100644 doc/content/modules/user-manual/assets/images/explorer-expression-full-text.png create mode 100644 doc/content/modules/user-manual/pages/features/expressions.adoc create mode 100644 frontend/syson-components/src/extensions/expressions/DeleteSysMLExpressionMenuContribution.tsx create mode 100644 frontend/syson-components/src/extensions/expressions/EditSysMLExpressionMenuContribution.tsx create mode 100644 frontend/syson-components/src/extensions/expressions/EditSysMLExpressionModal.tsx create mode 100644 frontend/syson-components/src/extensions/expressions/EditSysMLExpressionModal.types.ts create mode 100644 frontend/syson-components/src/extensions/expressions/NewSysMLExpressionMenuContribution.tsx create mode 100644 frontend/syson-components/src/extensions/expressions/useCreateExpression.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useCreateExpression.types.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useDeleteExpression.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useDeleteExpression.types.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useEditExpression.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useEditExpression.types.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useExpressionTextualRepresentation.ts create mode 100644 frontend/syson-components/src/extensions/expressions/useExpressionTextualRepresentation.types.ts diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index c061edd7a..94e6848e5 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -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 diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java index 4384dcac1..ddbf1b316 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java @@ -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; @@ -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; @@ -119,10 +119,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 detailViewHelpTextProviders; public SysMLv2PropertiesConfigurer(List composedAdapterFactoryDescriptors, ViewFormDescriptionConverter converter, IFeedbackMessageService feedbackMessageService, @@ -133,7 +133,7 @@ public SysMLv2PropertiesConfigurer(List 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 @@ -155,7 +155,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); diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/DeleteExpressionInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/DeleteExpressionInput.java new file mode 100644 index 000000000..bda589ea3 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/DeleteExpressionInput.java @@ -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 { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationInput.java new file mode 100644 index 000000000..24db44567 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationInput.java @@ -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 { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationPayload.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationPayload.java new file mode 100644 index 000000000..3afd3f2b7 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/dto/ExpressionTextualRepresentationPayload.java @@ -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); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/EditingContextExpressionTextualRepresentationDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/EditingContextExpressionTextualRepresentationDataFetcher.java new file mode 100644 index 000000000..e1a53069a --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/EditingContextExpressionTextualRepresentationDataFetcher.java @@ -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> { + + private static final String ELEMENT_ID_ARGUMENT = "elementId"; + + private final IEditingContextDispatcher editingContextDispatcher; + + public EditingContextExpressionTextualRepresentationDataFetcher(IEditingContextDispatcher editingContextDispatcher) { + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture 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(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/MutationDeleteExpressionDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/MutationDeleteExpressionDataFetcher.java new file mode 100644 index 000000000..fd3d60a8a --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/graphql/MutationDeleteExpressionDataFetcher.java @@ -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> { + + 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 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(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/DeleteExpressionEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/DeleteExpressionEventHandler.java new file mode 100644 index 000000000..e8bb9c4b0 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/DeleteExpressionEventHandler.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * 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.services; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventHandler; +import org.eclipse.sirius.components.collaborative.messages.ICollaborativeMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.syson.application.expressions.dto.DeleteExpressionInput; +import org.eclipse.syson.services.DeleteService; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; +import org.springframework.stereotype.Service; + +import reactor.core.publisher.Sinks; + +/** + * Event handler for the {@code deleteExpression} mutation. + * + * @author pcdavid + */ +@Service +public class DeleteExpressionEventHandler implements IEditingContextEventHandler { + + private final IObjectSearchService objectSearchService; + + private final MetamodelQueryElementService metamodelQueryElementService; + + private final ICollaborativeMessageService messageService; + + private final DeleteService deleteService; + + public DeleteExpressionEventHandler(IObjectSearchService objectSearchService, ICollaborativeMessageService messageService) { + this.objectSearchService = Objects.requireNonNull(objectSearchService); + this.metamodelQueryElementService = new MetamodelQueryElementService(); + this.messageService = Objects.requireNonNull(messageService); + this.deleteService = new DeleteService(); + } + + @Override + public boolean canHandle(IEditingContext editingContext, IInput input) { + return input instanceof DeleteExpressionInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, IInput input) { + IPayload payload; + if (input instanceof DeleteExpressionInput deleteExpressionInput) { + Optional optionalExpression = this.objectSearchService.getObject(editingContext, deleteExpressionInput.parentElementId()) + .filter(Element.class::isInstance) + .map(Element.class::cast) + .flatMap(element -> this.metamodelQueryElementService.findSingleExpressionDefinition(element)); + if (optionalExpression.isPresent()) { + this.deleteService.deleteFromModel(optionalExpression.get()); + var changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input); + changeDescriptionSink.tryEmitNext(changeDescription); + payload = new SuccessPayload(input.id()); + } else { + payload = new ErrorPayload(input.id(), this.messageService.notFound()); + } + } else { + payload = new ErrorPayload(input.id(), this.messageService.invalidInput(DeleteExpressionInput.class.getName(), input.getClass().getName())); + } + payloadSink.tryEmitValue(payload); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/ExpressionTextualRepresentationEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/ExpressionTextualRepresentationEventHandler.java new file mode 100644 index 000000000..63ece7f61 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/expressions/services/ExpressionTextualRepresentationEventHandler.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.services; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventHandler; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.syson.application.expressions.dto.ExpressionTextualRepresentationInput; +import org.eclipse.syson.application.expressions.dto.ExpressionTextualRepresentationPayload; +import org.eclipse.syson.sysml.Expression; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; +import org.springframework.stereotype.Service; + +import reactor.core.publisher.Sinks; + +/** + * Event handler for the {@code expressionTextualRepresentation} query field on EditingContext. + * + * @author pcdavid + */ +@Service +public class ExpressionTextualRepresentationEventHandler implements IEditingContextEventHandler { + + private final IObjectSearchService objectSearchService; + + private final MetamodelQueryElementService metamodelQueryElementService; + + public ExpressionTextualRepresentationEventHandler(IObjectSearchService objectSearchService) { + this.objectSearchService = Objects.requireNonNull(objectSearchService); + this.metamodelQueryElementService = new MetamodelQueryElementService(); + } + + @Override + public boolean canHandle(IEditingContext editingContext, IInput input) { + return input instanceof ExpressionTextualRepresentationInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, IInput input) { + String textualRepresentation = ""; + if (input instanceof ExpressionTextualRepresentationInput expressionTextualRepresentationInput) { + Optional optionalExpression = this.objectSearchService.getObject(editingContext, expressionTextualRepresentationInput.elementId()) + .filter(Expression.class::isInstance) + .map(Expression.class::cast) + .filter(this.metamodelQueryElementService::isTopLevelExpression); + if (optionalExpression.isPresent()) { + textualRepresentation = this.metamodelQueryElementService.getExpressionTextualRepresentation(optionalExpression.get()); + } + } + payloadSink.tryEmitValue(new ExpressionTextualRepresentationPayload(input.id(), textualRepresentation)); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java index 3eb15621b..def9195d8 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java @@ -39,7 +39,6 @@ import org.eclipse.syson.application.configuration.SysMLv2PropertiesConfigurer; import org.eclipse.syson.form.services.api.IDetailsViewHelpTextProvider; import org.eclipse.syson.services.ImportService; -import org.eclipse.syson.services.UtilService; import org.eclipse.syson.sysml.AcceptActionUsage; import org.eclipse.syson.sysml.ActionUsage; import org.eclipse.syson.sysml.Annotation; @@ -60,6 +59,7 @@ import org.eclipse.syson.sysml.ReferenceSubsetting; import org.eclipse.syson.sysml.ReferenceUsage; import org.eclipse.syson.sysml.Relationship; +import org.eclipse.syson.sysml.ResultExpressionMembership; import org.eclipse.syson.sysml.ReturnParameterMembership; import org.eclipse.syson.sysml.StateDefinition; import org.eclipse.syson.sysml.StateUsage; @@ -70,9 +70,7 @@ import org.eclipse.syson.sysml.Type; import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.metamodel.services.ElementInitializerSwitch; -import org.eclipse.syson.sysml.textual.SysMLElementSerializer; -import org.eclipse.syson.sysml.textual.SysMLSerializingOptions; -import org.eclipse.syson.sysml.textual.utils.FileNameDeresolver; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; /** * Java services needed to execute the AQL expressions used in the {@link SysMLv2PropertiesConfigurer}. @@ -95,9 +93,11 @@ public class DetailsViewService { private final EEnumLiteral unsetEnumLiteral; - private final UtilService utilService; + private final MetamodelQueryElementService metamodelQueryElementService; - public DetailsViewService(List composedAdapterFactoryDescriptors, IFeedbackMessageService feedbackMessageService, IReadOnlyObjectPredicate readOnlyObjectPredicate, List detailsViewHelpTextProviders) { + public DetailsViewService(List composedAdapterFactoryDescriptors, IFeedbackMessageService feedbackMessageService, IReadOnlyObjectPredicate readOnlyObjectPredicate, + MetamodelQueryElementService metamodelQueryElementService, + List detailsViewHelpTextProviders) { this.composedAdapterFactoryDescriptors = Objects.requireNonNull(composedAdapterFactoryDescriptors); this.feedbackMessageService = Objects.requireNonNull(feedbackMessageService); this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate); @@ -107,7 +107,7 @@ public DetailsViewService(List composedAdapterFactoryDescriptors, IF this.unsetEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral(); this.unsetEnumLiteral.setName("unset"); this.unsetEnumLiteral.setLiteral("unset"); - this.utilService = new UtilService(); + this.metamodelQueryElementService = Objects.requireNonNull(metamodelQueryElementService); } public String getDetailsViewLabel(Element element, EStructuralFeature eStructuralFeature) { @@ -574,8 +574,8 @@ public Element getFeatureValue(Element self) { Element result = null; if (self instanceof FeatureValue featureValue && featureValue.getValue() != null) { result = featureValue; - } else if (self instanceof Feature feature && this.utilService.getValuation(feature) != null && this.utilService.getValuation(feature).getValue() != null) { - result = this.utilService.getValuation(feature); + } else if (self instanceof Feature feature) { + result = this.metamodelQueryElementService.getValueExpression(feature).orElse(null); } return result; } @@ -589,22 +589,41 @@ public Element getFeatureValue(Element self) { */ public String getValueExpressionTextualRepresentation(FeatureValue featureValue) { Expression value = featureValue.getValue(); - String result = ""; - if (value != null) { - SysMLSerializingOptions options = new SysMLSerializingOptions.Builder() - .lineSeparator("\n") - .nameDeresolver(new FileNameDeresolver()) - .indentation("\t") - .needEscapeCharacter(false) - .build(); - String textualFormat = new SysMLElementSerializer(options, s -> { - // Do nothing for now - }).doSwitch(value); - if (textualFormat != null) { - result = textualFormat; - } - } - return result; + return this.getExpressionAsText(value); + } + + /** + * Gets the textual representation of the value of an actual {@link Expression}. + * + * @param expression + * an {@link Expression} + * @return a textual representation of the expression (or empty string if none) + */ + public String getExpressionTextualRepresentation(Expression expression) { + return this.getExpressionAsText(expression); + } + + /** + * Gets the textual representation of the value of a {@link ResultExpressionMembership}. + * + * @param resultExpression + * a {@link ResultExpressionMembership} + * @return a textual representation of the value (or empty string if none) + */ + public String getResultExpressionTextualRepresentation(ResultExpressionMembership resultExpression) { + Expression value = resultExpression.getOwnedResultExpression(); + return this.getExpressionAsText(value); + } + + /** + * Returns the serialized representation of an expression as plain text. + * + * @param expression + * the Expression + * @return the plain text representation of the expression. + */ + private String getExpressionAsText(Expression expression) { + return this.metamodelQueryElementService.getExpressionTextualRepresentation(expression); } /** diff --git a/backend/application/syson-application-configuration/src/main/resources/schema/expressions.graphqls b/backend/application/syson-application-configuration/src/main/resources/schema/expressions.graphqls new file mode 100644 index 000000000..e02595d6d --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/resources/schema/expressions.graphqls @@ -0,0 +1,15 @@ +extend type EditingContext { + expressionTextualRepresentation(elementId: ID!): String +} + +extend type Mutation { + deleteExpression(input: DeleteExpressionInput!): DeleteExpressionPayload! +} + +input DeleteExpressionInput { + id: ID! + editingContextId: String! + parentElementId: String! +} + +union DeleteExpressionPayload = ErrorPayload | SuccessPayload diff --git a/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java b/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java index 0f48b5c95..3e85799c0 100644 --- a/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java +++ b/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java @@ -30,6 +30,7 @@ import org.eclipse.syson.sysml.Package; import org.eclipse.syson.sysml.SysmlFactory; import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; import org.eclipse.syson.sysml.util.ElementUtil; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -49,7 +50,7 @@ public void setUp() { // SysON for the moment. List composedAdapterFactoryDescriptors = List.of(); this.detailsViewService = new DetailsViewService(composedAdapterFactoryDescriptors, new IFeedbackMessageService.NoOp(), - new ComposedReadOnlyObjectPredicate(List.of(new SysONReadOnlyObjectPredicateDelegate()), new DefaultReadOnlyObjectPredicate()), List.of()); + new ComposedReadOnlyObjectPredicate(List.of(new SysONReadOnlyObjectPredicateDelegate()), new DefaultReadOnlyObjectPredicate()), new MetamodelQueryElementService(), List.of()); } @Test diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/explorer/view/SysONExplorerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/explorer/view/SysONExplorerTests.java index a8e99293e..6247ac35d 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/explorer/view/SysONExplorerTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controller/explorer/view/SysONExplorerTests.java @@ -793,7 +793,7 @@ public void sysONExplorerTreeItemContextMenuEntriesTest() { var menuEntriesIds = this.treeItemContextMenuTester.getContextMenuEntries(GeneralViewEmptyTestProjectData.EDITING_CONTEXT, treeId.get(), GeneralViewEmptyTestProjectData.SemanticIds.VIEW_USAGE_ID); // no NewRepresentation on a ViewUsage which already contains a standard diagram or requirements-table - assertThat(menuEntriesIds).hasSize(4) + assertThat(menuEntriesIds).hasSize(5) .contains(ExplorerTreeItemContextMenuEntryProvider.NEW_OBJECT) .contains(SysONExplorerTreeItemContextMenuEntryProvider.NEW_OBJECTS_FROM_TEXT_MENU_ENTRY_CONTRIBUTION_ID) .contains(ExplorerTreeItemContextMenuEntryProvider.EXPAND_ALL); @@ -879,14 +879,7 @@ public void sysONExplorerTreeExpressionLabelTest() { public void sysONExplorerHidesExpressionInternalsByDefault() { List 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 expandedItemIds = ExpressionSamplesProjectData.SemanticIds.ALL_IDS; var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, expandedItemIds, defaultFilters); var input = new ExplorerEventInput(UUID.randomUUID(), ExpressionSamplesProjectData.EDITING_CONTEXT_ID, explorerRepresentationId); @@ -905,7 +898,7 @@ public void sysONExplorerHidesExpressionInternalsByDefault() { var packageItem = documentItem.getChildren().get(0); assertThat(packageItem.getLabel().toString()).isEqualTo("Expressions"); - assertThat(packageItem.getChildren()).hasSize(7); + assertThat(packageItem.getChildren()).hasSize(6); var tankItem = this.getChildByLabel(packageItem, "Tank"); assertThat(tankItem).isPresent(); @@ -940,14 +933,7 @@ public void sysONExplorerExpressionInternalsCanBeRevealed() { // Keep all defaults but HIDE_EXPRESSION_INTERNALS_ID List 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 expandedItemIds = ExpressionSamplesProjectData.SemanticIds.ALL_IDS; var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, expandedItemIds, activeFilters); var input = new ExplorerEventInput(UUID.randomUUID(), ExpressionSamplesProjectData.EDITING_CONTEXT_ID, explorerRepresentationId); @@ -966,7 +952,7 @@ public void sysONExplorerExpressionInternalsCanBeRevealed() { var packageItem = documentItem.getChildren().get(0); assertThat(packageItem.getLabel().toString()).isEqualTo("Expressions"); - assertThat(packageItem.getChildren()).hasSize(7); + assertThat(packageItem.getChildren()).hasSize(6); var tankItem = this.getChildByLabel(packageItem, "Tank"); assertThat(tankItem).isPresent(); diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/ExpressionsControllersIntegrationTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/ExpressionsControllersIntegrationTests.java new file mode 100644 index 000000000..a63ae0383 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/ExpressionsControllersIntegrationTests.java @@ -0,0 +1,649 @@ +/******************************************************************************* + * 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.controllers.expressions; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.trees.tests.TreeEventPayloadConsumer.assertRefreshedTreeThat; + +import com.jayway.jsonpath.JsonPath; + +import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IIdentityService; +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionInput; +import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload; +import org.eclipse.sirius.components.graphql.tests.api.IExecuteEditingContextFunctionRunner; +import org.eclipse.sirius.web.application.views.explorer.ExplorerEventInput; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.sirius.web.tests.services.explorer.ExplorerEventSubscriptionRunner; +import org.eclipse.sirius.web.tests.services.representation.RepresentationIdBuilder; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.GivenSysONServer; +import org.eclipse.syson.application.controllers.expressions.graphql.CreateExpressionMutationRunner; +import org.eclipse.syson.application.controllers.expressions.graphql.DeleteExpressionMutationRunner; +import org.eclipse.syson.application.controllers.expressions.graphql.EditExpressionMutationRunner; +import org.eclipse.syson.application.controllers.expressions.graphql.ExpressionTextualRepresentationQueryRunner; +import org.eclipse.syson.application.data.ExpressionSamplesProjectData; +import org.eclipse.syson.application.expressions.dto.DeleteExpressionInput; +import org.eclipse.syson.services.explorer.api.IExplorerDefaultFiltersSearchService; +import org.eclipse.syson.sysml.AttributeUsage; +import org.eclipse.syson.sysml.ConstraintUsage; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; +import org.eclipse.syson.sysml.FeatureValue; +import org.eclipse.syson.sysml.TransitionUsage; +import org.eclipse.syson.sysml.dto.CreateExpressionInput; +import org.eclipse.syson.sysml.dto.CreateExpressionSuccessPayload; +import org.eclipse.syson.sysml.dto.EditExpressionInput; +import org.eclipse.syson.sysml.dto.EditExpressionSuccessPayload; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; +import org.eclipse.syson.tree.explorer.view.SysONTreeViewDescriptionProvider; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.transaction.TestTransaction; +import org.springframework.transaction.annotation.Transactional; + +import reactor.test.StepVerifier; + +/** + * Tests for GraphQL Queries and Mutations related to SysML Expressions. + * + * @author pcdavid + */ +@Transactional +@SuppressWarnings("checkstyle:MultipleStringLiterals") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class ExpressionsControllersIntegrationTests extends AbstractIntegrationTests { + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private ExplorerEventSubscriptionRunner explorerEventSubscriptionRunner; + + @Autowired + private RepresentationIdBuilder representationIdBuilder; + + @Autowired + private SysONTreeViewDescriptionProvider sysonTreeViewDescriptionProvider; + + @Autowired + private IExplorerDefaultFiltersSearchService explorerDefaultFiltersSearchService; + + @Autowired + private IObjectSearchService objectSearchService; + + @Autowired + private IIdentityService identityService; + + @Autowired + private IExecuteEditingContextFunctionRunner executeEditingContextFunctionRunner; + + @Autowired + private ExpressionTextualRepresentationQueryRunner expressionTextualRepresentationQueryRunner; + + @Autowired + private CreateExpressionMutationRunner createExpressionMutationRunner; + + @Autowired + private EditExpressionMutationRunner editExpressionMutationRunner; + + @Autowired + private DeleteExpressionMutationRunner deleteExpressionMutationRunner; + + private String sysONExplorerTreeDescriptionId; + + private MetamodelQueryElementService metamodelQueryElementService; + + @BeforeEach + public void beforeEach() { + this.sysONExplorerTreeDescriptionId = this.sysonTreeViewDescriptionProvider.getDescriptionId(); + this.givenInitialServerState.initialize(); + this.metamodelQueryElementService = new MetamodelQueryElementService(); + } + + @DisplayName("GIVEN a SysML attribute which does not have an initial or default value, WHEN creating a new expression on it THEN the new expression is created with proper name resolution") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void canCreateExpressionInEmptyAttribute() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + Runnable checkPressureAttributeHasNoValueExpression = this.checkElementHasNoExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_ATTRIBUTE_ID, + AttributeUsage.class); + + Runnable createExpressionOnPressureAttribute = this.createExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_ATTRIBUTE_ID, "maxPressure / 2"); + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkPressureAttributeHasExpectedValueExpression = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_PRESSURE_ATTRIBUTE_ID, + AttributeUsage.class, + new AtomicReference<>(), "maxPressure / 2"); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkPressureAttributeHasNoValueExpression) + .then(createExpressionOnPressureAttribute) + .consumeNextWith(treeRefreshed) + .then(checkPressureAttributeHasExpectedValueExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML attribute which does have an existing expression, WHEN trying to create a new expression on it THEN the new expression is created with proper name resolution") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void canNotCreateExpressionInNonEmptyAttribute() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + Runnable checkMaxVolumeAttributeHasExistingValueExpression = this.checkElementHasExpression(editingContextId, + ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID, AttributeUsage.class, new AtomicReference<>(), + "100.0 * minVolume"); + + Runnable tryCreateExpressionOnMaxVolumnAttribute = () -> { + var input = new CreateExpressionInput(UUID.randomUUID(), editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID, "42"); + var result = this.createExpressionMutationRunner.run(input); + String typename = JsonPath.read(result.data(), "$.data.createExpression.__typename"); + assertThat(typename).isEqualTo(ErrorPayload.class.getSimpleName()); + }; + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkMaxVolumeAttributeHasExistingValueExpression) + .then(tryCreateExpressionOnMaxVolumnAttribute) + .then(checkMaxVolumeAttributeHasExistingValueExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML attribute that has an existing expression, WHEN editing the expression to a new one THEN the attribute's expression is replaced") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void textEditAttributeExpression() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + var existingExpressionId = new AtomicReference(); + + Runnable checkInitialExpression = this.checkElementHasExpression(editingContextId, + ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID, AttributeUsage.class, existingExpressionId, + "100.0 * minVolume"); + + Runnable editExpressionOnMaxVolumeAttribute = this.editExpression(editingContextId, existingExpressionId::get, "50 * minVolume"); + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkExpressionUpdated = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID, + AttributeUsage.class, + existingExpressionId, + "50 * minVolume"); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkInitialExpression) + .then(editExpressionOnMaxVolumeAttribute) + .consumeNextWith(treeRefreshed) + .then(checkExpressionUpdated) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML constraint which does not have a predicate expression, WHEN creating a new expression on it THEN the new expression is created with proper name resolution") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void canCreateExpressionInEmptyConstraint() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + Runnable checkNoInitialExpression = this.checkElementHasNoExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_ASSUME_ID, + ConstraintUsage.class); + + Runnable createExpression = this.createExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_ASSUME_ID, "s.enabled == true"); + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkCreatedExpression = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_ASSUME_ID, ConstraintUsage.class, + new AtomicReference<>(), "s.enabled == true"); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkNoInitialExpression) + .then(createExpression) + .consumeNextWith(treeRefreshed) + .then(checkCreatedExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML transition which does not have a guard expression, WHEN creating a new expression on it THEN the new expression is created with proper name resolution") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void canCreateGuardExpressionInEmptyTransition() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + Runnable checkNoInitialExpression = this.checkElementHasNoExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_HEATING_TRANSITION_ID, + TransitionUsage.class); + + Runnable createExpression = this.createExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_HEATING_TRANSITION_ID, "currentTemp < targetTemp - tolerance"); + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkCreatedExpression = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_HEATING_TRANSITION_ID, TransitionUsage.class, + new AtomicReference<>(), "currentTemp < targetTemp - tolerance"); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkNoInitialExpression) + .then(createExpression) + .consumeNextWith(treeRefreshed) + .then(checkCreatedExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML transition with a guard expression, WHEN editing the expression on it THEN the new expression is modified with proper name resolution") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void canEditGuardExpressionOnTransition() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + var expressionId = new AtomicReference(); + + Runnable checkNoInitialExpression = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_COOLING_TRANSITION_ID, + TransitionUsage.class, expressionId, "currentTemp > targetTemp + tolerance"); + + Runnable createExpression = this.editExpression(editingContextId, expressionId::get, "currentTemp >= targetTemp + (tolerance * 0.9)"); + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkCreatedExpression = this.checkElementHasExpression(editingContextId, ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_COOLING_TRANSITION_ID, TransitionUsage.class, + new AtomicReference<>(), "currentTemp >= targetTemp + tolerance * 0.9"); // Note that the "()" from the + // source are lost in the + // serialization + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkNoInitialExpression) + .then(createExpression) + .consumeNextWith(treeRefreshed) + .then(checkCreatedExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML attribute that has an existing expression, WHEN editing the expression to an invalid new value THEN the attribute's expression is not modified") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void editAttributeExpressionWithInvalidNewValue() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + var existingExpressionId = new AtomicReference(); + + Runnable checkMaxVolumeAttributeHasExistingValueExpression = this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalMaxVolumeAttribute = this.objectSearchService.getObject(editingContext, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID); + assertThat(optionalMaxVolumeAttribute).containsInstanceOf(AttributeUsage.class); + var maxVolumeAttribute = (AttributeUsage) optionalMaxVolumeAttribute.get(); + Optional valueExpression = this.metamodelQueryElementService.getValueExpression(maxVolumeAttribute); + assertThat(valueExpression).isNotEmpty(); + assertThat(this.metamodelQueryElementService.getExpressionTextualRepresentation(valueExpression.get())).isEqualTo("100.0 * minVolume"); + existingExpressionId.set(this.identityService.getId(valueExpression.get())); + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalMaxVolumeAttribute.get()); + }); + + Runnable editExpressionOnMaxVolumeAttributeWithInvalidValue = () -> { + var input = new EditExpressionInput(UUID.randomUUID(), editingContextId, existingExpressionId.get(), "50 * minVolumeTypo"); + var result = this.editExpressionMutationRunner.run(input); + String typename = JsonPath.read(result.data(), "$.data.editExpression.__typename"); + assertThat(typename).isEqualTo(ErrorPayload.class.getSimpleName()); + String messageLevel = JsonPath.read(result.data(), "$.data.editExpression.messages[0].level"); + assertThat(messageLevel).isEqualTo("WARNING"); + String messageBody = JsonPath.read(result.data(), "$.data.editExpression.messages[0].body"); + assertThat(messageBody).contains("Unable to resolve name 'minVolumeTypo' for reference 'memberElement' on element '[Membership] Expressions::Tank::maxVolume"); + }; + + Runnable checkMaxVolumeAttributeHasInitialValueExpression = this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalMaxVolumeAttribute = this.objectSearchService.getObject(editingContext, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID); + assertThat(optionalMaxVolumeAttribute).containsInstanceOf(AttributeUsage.class); + var maxVolumeAttribute = (AttributeUsage) optionalMaxVolumeAttribute.get(); + Optional valueExpression = this.metamodelQueryElementService.getValueExpression(maxVolumeAttribute); + assertThat(valueExpression).isNotEmpty(); + assertThat(this.metamodelQueryElementService.getExpressionTextualRepresentation(valueExpression.get())).isEqualTo("100.0 * minVolume"); + // Check this is indeed the exact same element as before + String newValueExpressionId = this.identityService.getId(valueExpression.get()); + assertThat(newValueExpressionId).isEqualTo(existingExpressionId.get()); + + // Make sure we did not create an additional invalid FeatureValue and left it around. + assertThat(maxVolumeAttribute.getOwnedRelationship().stream().filter(FeatureValue.class::isInstance)).hasSize(1); + + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalMaxVolumeAttribute.get()); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkMaxVolumeAttributeHasExistingValueExpression) + .then(editExpressionOnMaxVolumeAttributeWithInvalidValue) + .then(checkMaxVolumeAttributeHasInitialValueExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN an attribute with an expression, WHEN invoking delete expression on it THEN the expression and its owning relationship are removed from the model") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void deleteExpressionFromParentAttribute() { + this.deleteExistingExpressionFromParentElement(ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID); + } + + @DisplayName("GIVEN an assume constraint in a concern with an expression, WHEN invoking delete expression on it THEN the expression and its owning relationship are removed from the model") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void deleteExpressionFromParentConstraint() { + this.deleteExistingExpressionFromParentElement(ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_REQUIRE_ID); + } + + @DisplayName("GIVEN a transition with a guard expression, WHEN invoking delete expression on it THEN the expression and its owning relationship are removed from the model") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void deleteExpressionFromParentTransition() { + this.deleteExistingExpressionFromParentElement(ExpressionSamplesProjectData.SemanticIds.THERMAL_CONTROL_TO_COOLING_TRANSITION_ID); + } + + /** + * Invoke the {@code deleteExpression()} mutation on a parent element which contains a top-level expression + * definition, and checks that both the expression and its owning relationship are correctly removed from the model. + * + * @param parentElementId + * the id of the parent element of the expression to remove. + */ + public void deleteExistingExpressionFromParentElement(String parentElementId) { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var explorerInput = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(explorerInput).flux(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + var initialExpressionId = new AtomicReference(); + var initialExpressionOwningRelationshipId = new AtomicReference(); + + Runnable checkParentElementExistsAndHasExpression = this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalParentElement = this.objectSearchService.getObject(editingContext, parentElementId); + assertThat(optionalParentElement).containsInstanceOf(Element.class); + var parentElement = (Element) optionalParentElement.get(); + Optional optionalExpression = this.metamodelQueryElementService.findSingleExpressionDefinition(parentElement); + assertThat(optionalExpression).containsInstanceOf(Expression.class); + initialExpressionId.set(this.identityService.getId(optionalExpression.get())); + initialExpressionOwningRelationshipId.set(this.identityService.getId(optionalExpression.get().getOwningRelationship())); + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalParentElement.get()); + }); + + Runnable deleteExpressionFromParentElement = () -> { + var input = new DeleteExpressionInput(UUID.randomUUID(), editingContextId, parentElementId); + var result = this.deleteExpressionMutationRunner.run(input); + String typename = JsonPath.read(result.data(), "$.data.deleteExpression.__typename"); + assertThat(typename).isEqualTo(SuccessPayload.class.getSimpleName()); + }; + + Consumer treeRefreshed = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + assertThat(tree.getId()).isEqualTo(treeId.get()); + }); + + Runnable checkParentElementHasNoExpression = this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalParentElement = this.objectSearchService.getObject(editingContext, parentElementId); + assertThat(optionalParentElement).containsInstanceOf(Element.class); + var parentElement = (Element) optionalParentElement.get(); + Optional optionalExpression = this.metamodelQueryElementService.findSingleExpressionDefinition(parentElement); + assertThat(optionalExpression).isEmpty(); + + // The original Expression element and its Relationship should no longer be part of the model + assertThat(this.objectSearchService.getObject(editingContext, initialExpressionId.get())).isEmpty(); + assertThat(this.objectSearchService.getObject(editingContext, initialExpressionOwningRelationshipId.get())).isEmpty(); + + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), parentElement); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkParentElementExistsAndHasExpression) + .then(deleteExpressionFromParentElement) + .consumeNextWith(treeRefreshed) + .then(checkParentElementHasNoExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a SysML model with expressions, WHEN requesting the textual representation of an actual top-level Expression element, THEN its textual representation is returned") + @GivenSysONServer({ ExpressionSamplesProjectData.SCRIPT_PATH }) + @Test + public void topLevelExpressionTextualRepresentation() { + String editingContextId = ExpressionSamplesProjectData.EDITING_CONTEXT_ID; + + List defaultFilters = this.explorerDefaultFiltersSearchService.findTreeDefaultFilterIds(editingContextId, this.sysONExplorerTreeDescriptionId); + var explorerRepresentationId = this.representationIdBuilder.buildExplorerRepresentationId(this.sysONExplorerTreeDescriptionId, List.of(), defaultFilters); + var input = new ExplorerEventInput(UUID.randomUUID(), editingContextId, explorerRepresentationId); + var flux = this.explorerEventSubscriptionRunner.run(input).flux(); + TestTransaction.flagForCommit(); + TestTransaction.end(); + + var treeId = new AtomicReference(); + Consumer initialTreeContentConsumer = assertRefreshedTreeThat(tree -> { + assertThat(tree).isNotNull(); + treeId.set(tree.getId()); + }); + + // The Tank part and its attribute are not themselves expressions => "" + var checkTank = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_ID, ""); + var checkTankAttribute = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_ID, ""); + // The actual attribute default value expression however should be correctly represented + var checkTankAttributeValueExpression = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.TANK_MAX_VOLUME_ATTRIBUTE_VALUE_ID, + "100.0 * minVolume"); + + var checkPerformanceConcern = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_ID, ""); + // A ConstaintUsage *is* an Expression from the point of view of SysML's type hierarchy, but not a top-level + // Expression, so we expect "" here. + var checkPerformanceConcernAssumeConstraint = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_ASSUME_ID, ""); + var checkPerformanceConcernRequireConstraint = this.checkExpressiontTextualRepresentation(editingContextId, ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_REQUIRE_ID, ""); + // require s.samplingRate >= 50.0 & s.currentValue != 0.0 | s.errorCount == 0 + var checkPerformanceConcernRequireConstraintExpression = this.checkExpressiontTextualRepresentation(editingContextId, + ExpressionSamplesProjectData.SemanticIds.PERFORMANCE_CONCERN_REQUIRE_EXPRESSION_ID, "s.samplingRate >= 50.0 & s.currentValue != 0.0 | s.errorCount == 0"); + + StepVerifier.create(flux) + .consumeNextWith(initialTreeContentConsumer) + .then(checkTank) + .then(checkTankAttribute) + .then(checkTankAttributeValueExpression) + .then(checkPerformanceConcern) + .then(checkPerformanceConcernAssumeConstraint) + .then(checkPerformanceConcernRequireConstraint) + .then(checkPerformanceConcernRequireConstraintExpression) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + + /** + * Executes a function in the editing context with the specified id (which is assumed to be loaded). The function + * can perform JUnit assertions to verify the state of the semantic model in the editing context. + */ + private Runnable semanticCheck(String editingContextId, BiFunction checker) { + return () -> { + var input = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), editingContextId, checker); + var payload = this.executeEditingContextFunctionRunner.execute(input).block(); + assertThat(payload).isInstanceOf(ExecuteEditingContextFunctionSuccessPayload.class); + }; + } + + private Runnable createExpression(String editingContextId, String parentElementId, String expressionContent) { + return () -> { + var input = new CreateExpressionInput(UUID.randomUUID(), editingContextId, parentElementId, expressionContent); + var result = this.createExpressionMutationRunner.run(input); + String typename = JsonPath.read(result.data(), "$.data.createExpression.__typename"); + assertThat(typename).isEqualTo(CreateExpressionSuccessPayload.class.getSimpleName()); + }; + } + + private Runnable editExpression(String editingContextId, Supplier elementId, String expressionContent) { + return () -> { + var input = new EditExpressionInput(UUID.randomUUID(), editingContextId, elementId.get(), expressionContent); + var result = this.editExpressionMutationRunner.run(input); + String typename = JsonPath.read(result.data(), "$.data.editExpression.__typename"); + assertThat(typename).isEqualTo(EditExpressionSuccessPayload.class.getSimpleName()); + }; + } + + private Runnable checkExpressiontTextualRepresentation(String editingContextId, String elementId, String expectedTextualRepresentation) { + return () -> { + Map variables = Map.of("editingContextId", editingContextId, "elementId", elementId); + var result = this.expressionTextualRepresentationQueryRunner.run(variables); + String textualRepresentation = JsonPath.read(result.data(), "$.data.viewer.editingContext.expressionTextualRepresentation"); + assertThat(textualRepresentation).as("elementId: {}", elementId).isEqualTo(expectedTextualRepresentation); + }; + } + + private Runnable checkElementHasNoExpression(String editingContextId, String elementId, Class expectedElementType) { + return this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalElement = this.objectSearchService.getObject(editingContext, elementId); + assertThat(optionalElement).containsInstanceOf(expectedElementType); + T element = expectedElementType.cast(optionalElement.get()); + Optional valueExpression = this.metamodelQueryElementService.findSingleExpressionDefinition(element); + assertThat(valueExpression).isEmpty(); + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalElement.get()); + }); + } + + private Runnable checkElementHasExpression(String editingContextId, String elementId, Class expectedElementType, AtomicReference expressionId, + String expectedExpressionTextualRepresentation) { + return this.semanticCheck(editingContextId, (editingContext, input) -> { + var optionalElement = this.objectSearchService.getObject(editingContext, elementId); + assertThat(optionalElement).containsInstanceOf(expectedElementType); + T element = expectedElementType.cast(optionalElement.get()); + Optional valueExpression = this.metamodelQueryElementService.findSingleExpressionDefinition(element); + assertThat(valueExpression).isNotEmpty(); + expressionId.set(this.identityService.getId(valueExpression.get())); + assertThat(this.metamodelQueryElementService.getExpressionTextualRepresentation(valueExpression.get())).isEqualTo(expectedExpressionTextualRepresentation); + return new ExecuteEditingContextFunctionSuccessPayload(input.id(), optionalElement.get()); + }); + } +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/CreateExpressionMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/CreateExpressionMutationRunner.java new file mode 100644 index 000000000..6b654d992 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/CreateExpressionMutationRunner.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.controllers.expressions.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.graphql.tests.api.GraphQLResult; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.eclipse.syson.sysml.dto.CreateExpressionInput; +import org.springframework.stereotype.Service; + +/** + * Used to invoke the createExpression mutation via the GraphQL API. + * + * @author pcdavid + */ +@Service +public class CreateExpressionMutationRunner implements IMutationRunner { + + private static final String CREATE_EXPRESSION_MUTATION = """ + mutation createExpression($input: CreateExpressionInput!) { + createExpression(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on CreateExpressionSuccessPayload { + newExpressionId + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public CreateExpressionMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public GraphQLResult run(CreateExpressionInput input) { + return this.graphQLRequestor.execute(CREATE_EXPRESSION_MUTATION, input); + } +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/DeleteExpressionMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/DeleteExpressionMutationRunner.java new file mode 100644 index 000000000..abd7b616e --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/DeleteExpressionMutationRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.controllers.expressions.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.graphql.tests.api.GraphQLResult; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.eclipse.syson.application.expressions.dto.DeleteExpressionInput; +import org.springframework.stereotype.Service; + +/** + * Used to invoke the deleteExpression mutation via the GraphQL API. + * + * @author pcdavid + */ +@Service +public class DeleteExpressionMutationRunner implements IMutationRunner { + + private static final String DELETE_EXPRESSION_MUTATION = """ + mutation deleteExpression($input: DeleteExpressionInput!) { + deleteExpression(input: $input) { + __typename + ... on SuccessPayload { + messages { + body + level + } + } + ... on ErrorPayload { + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public DeleteExpressionMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public GraphQLResult run(DeleteExpressionInput input) { + return this.graphQLRequestor.execute(DELETE_EXPRESSION_MUTATION, input); + } +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/EditExpressionMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/EditExpressionMutationRunner.java new file mode 100644 index 000000000..cb8e43023 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/EditExpressionMutationRunner.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.controllers.expressions.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.graphql.tests.api.GraphQLResult; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.eclipse.syson.sysml.dto.EditExpressionInput; +import org.springframework.stereotype.Service; + +/** + * Used to invoke the editExpression mutation via the GraphQL API. + * + * @author pcdavid + */ +@Service +public class EditExpressionMutationRunner implements IMutationRunner { + + private static final String EDIT_EXPRESSION_MUTATION = """ + mutation editExpression($input: EditExpressionInput!) { + editExpression(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on EditExpressionSuccessPayload { + newExpressionId + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public EditExpressionMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public GraphQLResult run(EditExpressionInput input) { + return this.graphQLRequestor.execute(EDIT_EXPRESSION_MUTATION, input); + } +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/ExpressionTextualRepresentationQueryRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/ExpressionTextualRepresentationQueryRunner.java new file mode 100644 index 000000000..c279d886b --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/expressions/graphql/ExpressionTextualRepresentationQueryRunner.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * 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.controllers.expressions.graphql; + +import java.util.Map; +import java.util.Objects; + +import org.eclipse.sirius.components.graphql.tests.api.GraphQLResult; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IQueryRunner; +import org.springframework.stereotype.Service; + +/** + * User to fetch the textual representation of an expression. + * + * @author pcdavid + */ +@Service +public class ExpressionTextualRepresentationQueryRunner implements IQueryRunner { + private static final String QUERY = """ + query getExpressionTextualRepresentation($editingContextId: ID!, $elementId: ID!) { + viewer { + editingContext(editingContextId: $editingContextId) { + expressionTextualRepresentation(elementId: $elementId) + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public ExpressionTextualRepresentationQueryRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public GraphQLResult run(Map variables) { + return this.graphQLRequestor.execute(QUERY, variables); + } +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/ExpressionSamplesProjectData.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/ExpressionSamplesProjectData.java index cd12d1aad..4297d5cc2 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/ExpressionSamplesProjectData.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/ExpressionSamplesProjectData.java @@ -12,6 +12,8 @@ *******************************************************************************/ package org.eclipse.syson.application.data; +import java.util.List; + /** * Ids for project "Expression-Samples". * @@ -32,6 +34,8 @@ public static final class SemanticIds { public static final String TANK_ID = "2bde22f7-a834-4afa-84bf-1bae1bb434d8"; + public static final String TANK_PRESSURE_ATTRIBUTE_ID = "7479570e-234f-4603-a764-d45ba1228aad"; + 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"; @@ -40,5 +44,38 @@ public static final class SemanticIds { public static final String TANK_PRESSURE_LIMIT_CONSTRAINT_VALUE_ID = "faa3b115-5b07-4ecf-9147-0d58ceffaf9c"; + public static final String PERFORMANCE_CONCERN_ID = "da2296a4-25ed-4f04-abc8-d47f93cd223c"; + + public static final String PERFORMANCE_CONCERN_ASSUME_ID = "4fd2c402-15b7-4546-ad9c-7aa9419a1528"; + + public static final String PERFORMANCE_CONCERN_REQUIRE_ID = "6891b4f5-6f02-4c73-ae23-db88ad10b253"; + + public static final String PERFORMANCE_CONCERN_REQUIRE_EXPRESSION_ID = "6f2e1644-b09d-46a2-b155-fc123e0f2953"; + + public static final String THERMAL_CONTROL_STATE_DEFINITION_ID = "2efcf5d4-4948-4b7d-b779-f3f694eb8165"; + + public static final String THERMAL_CONTROL_TO_HEATING_TRANSITION_ID = "0b517687-ef3f-4057-9ce5-27e27f627a22"; + + public static final String THERMAL_CONTROL_TO_COOLING_TRANSITION_ID = "e1c27d0b-476e-42d4-9b81-b5f064d9cbbe"; + + public static final String THERMAL_CONTROL_TO_COOLING_TRANSITION_GUARD_EXPRESSION_ID = "ec67ead5-7739-4dd3-a82e-f1bb5ef34268"; + + public static final List ALL_IDS = List.of( + EXPRESSIONS_DOCUMENT_ID, + EXPRESSIONS_PACKAGE_ID, + TANK_ID, + TANK_PRESSURE_ATTRIBUTE_ID, + TANK_MAX_VOLUME_ATTRIBUTE_ID, + TANK_MAX_VOLUME_ATTRIBUTE_VALUE_ID, + TANK_PRESSURE_LIMIT_CONSTRAINT_ID, + TANK_PRESSURE_LIMIT_CONSTRAINT_VALUE_ID, + PERFORMANCE_CONCERN_ID, + PERFORMANCE_CONCERN_ASSUME_ID, + PERFORMANCE_CONCERN_REQUIRE_ID, + PERFORMANCE_CONCERN_REQUIRE_EXPRESSION_ID, + THERMAL_CONTROL_STATE_DEFINITION_ID, + THERMAL_CONTROL_TO_HEATING_TRANSITION_ID, + THERMAL_CONTROL_TO_COOLING_TRANSITION_ID, + THERMAL_CONTROL_TO_COOLING_TRANSITION_GUARD_EXPRESSION_ID); } } diff --git a/backend/application/syson-application/src/test/resources/scripts/database-content/ExpressionSamples.sql b/backend/application/syson-application/src/test/resources/scripts/database-content/ExpressionSamples.sql index bce471713..028199b38 100644 --- a/backend/application/syson-application/src/test/resources/scripts/database-content/ExpressionSamples.sql +++ b/backend/application/syson-application/src/test/resources/scripts/database-content/ExpressionSamples.sql @@ -27,7 +27,7 @@ INSERT INTO public.semantic_data (id, created_on, last_modified_on) VALUES ('aac -- Data for Name: document; Type: TABLE DATA; Schema: public; Owner: dbuser -- -INSERT INTO public.document (id, semantic_data_id, name, content, created_on, last_modified_on, is_read_only) VALUES ('ef3e6929-0415-4295-b42f-64bed8bd4f55', 'aac82b89-8d53-4b16-91b4-deccc180ba62', 'expressions.sysml', '{"json":{"version":"1.0","encoding":"utf-8"},"ns":{"sysml":"http://www.eclipse.org/syson/sysml"},"migration":{"lastMigrationPerformed":"DiagramStyleDescriptionAddMigrationParticipant","migrationVersion":"2026.5.0-202603171430"},"content":[{"id":"152e5a5b-2b71-4653-8b7f-d46df76cd595","eClass":"sysml:Namespace","data":{"eAnnotations":[{"source":"org.eclipse.syson.sysml.imported"}],"elementId":"cfa2873f-f2f4-475a-8817-9f73e2dff74f","ownedRelationship":[{"id":"bea4a5f8-cc39-4cc0-ab5c-226fcf86f737","eClass":"sysml:OwningMembership","data":{"elementId":"eeda408c-b3e7-41af-a52b-3463777d41c0","ownedRelatedElement":[{"id":"baf5ea6a-7861-4b92-8be2-3fe7a2ebc415","eClass":"sysml:Package","data":{"declaredName":"Expressions","elementId":"6ff78b89-10b8-44f5-817f-50ea23e0c620","ownedRelationship":[{"id":"d8072b8b-400f-4968-b1e2-6601ba10bdc7","eClass":"sysml:NamespaceImport","data":{"elementId":"f2a55343-1f9c-4cc6-9912-8ca86dab734e","importedNamespace":"sysml:LibraryPackage kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#40bb440c-5036-58e1-8675-5afccb8b8f1d"}},{"id":"63ed369c-92bd-48cf-ba76-147c1ec13316","eClass":"sysml:OwningMembership","data":{"elementId":"033678d4-289b-46d1-9704-d97a006fb024","ownedRelatedElement":[{"id":"2bde22f7-a834-4afa-84bf-1bae1bb434d8","eClass":"sysml:PartDefinition","data":{"declaredName":"Tank","elementId":"e5e396e4-635f-44a2-8d85-50e19b94a6e7","ownedRelationship":[{"id":"bd7b6c14-0803-423c-b5d9-f368d8c32e6d","eClass":"sysml:FeatureMembership","data":{"elementId":"66064f96-7440-4236-bb21-11bb8c61224c","ownedRelatedElement":[{"id":"15ccc1e3-16b9-4ddf-9959-43141f32d48e","eClass":"sysml:AttributeUsage","data":{"declaredName":"pressure","elementId":"7479570e-234f-4603-a764-d45ba1228aad","ownedRelationship":[{"id":"b4f4a75e-cc97-4a5a-a6a6-5bfafd5eede6","eClass":"sysml:FeatureValue","data":{"elementId":"3091dd86-0287-4371-aafd-db02ebc46345","ownedRelatedElement":[{"id":"1eae8ba0-03c9-4ff0-87a7-578abde5550f","eClass":"sysml:LiteralRational","data":{"elementId":"c62ef353-15a6-482e-8abe-3008cbc989cc"}}],"isInitial":true}},{"id":"470e47da-8c4f-45be-a841-5bb4fa82f8da","eClass":"sysml:FeatureTyping","data":{"elementId":"4f77e08f-1a50-4056-a6cb-283b6c0de857","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"15ccc1e3-16b9-4ddf-9959-43141f32d48e"}}],"isComposite":true}}]}},{"id":"27c51649-9b3b-471c-b846-33f10fe82332","eClass":"sysml:FeatureMembership","data":{"elementId":"747b5a9e-95de-4908-a7f0-3917cb4385ae","ownedRelatedElement":[{"id":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a","eClass":"sysml:AttributeUsage","data":{"declaredName":"maxPressure","elementId":"058dca9f-5c49-4ae6-8f71-5e11df5b4021","ownedRelationship":[{"id":"01c173ba-5433-45f6-a9ad-5abf786562c9","eClass":"sysml:FeatureValue","data":{"elementId":"2a6cd6e7-6af0-426b-b6e9-1749f4cae266","ownedRelatedElement":[{"id":"703297e9-e397-496c-ac9a-49b2afff4ba7","eClass":"sysml:LiteralRational","data":{"elementId":"6a768b6c-2898-4dfa-aa7c-2a7f3a9fd6e4","value":600.0}}]}},{"id":"bb766cff-de2c-469f-90b8-06bd35514038","eClass":"sysml:FeatureTyping","data":{"elementId":"9e91a82c-3c8b-43f5-96eb-a92781f5a8d8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a"}}],"isComposite":true}}]}},{"id":"77e243ce-1879-49a5-a4e6-ec8d91b8da9f","eClass":"sysml:FeatureMembership","data":{"elementId":"2a061597-9b75-422f-ac99-17317f4076a9","ownedRelatedElement":[{"id":"7c2ed44f-f991-4559-8594-cfd844160744","eClass":"sysml:AttributeUsage","data":{"declaredName":"volume","elementId":"87f09d7d-87a8-4edf-8c96-eb7d13c44702","ownedRelationship":[{"id":"9789b076-4604-4407-b662-6179ab76b2c5","eClass":"sysml:FeatureValue","data":{"elementId":"7625d338-d5ed-4050-bf6a-a22c75ea21af","ownedRelatedElement":[{"id":"a512cb6b-9395-48b9-88ba-fcb8b2754484","eClass":"sysml:LiteralRational","data":{"elementId":"cfa46233-fa49-4eef-b384-fc4a5861c39a","value":500.0}}]}},{"id":"91584942-a0c5-46f9-bd52-c252b9c0a285","eClass":"sysml:FeatureTyping","data":{"elementId":"cce82e52-823f-4f33-85ac-765af147c2f8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"7c2ed44f-f991-4559-8594-cfd844160744"}}],"isComposite":true}}]}},{"id":"f5d0e91d-5d51-490e-93cf-42662bdb62e8","eClass":"sysml:FeatureMembership","data":{"elementId":"a3c78e1d-535a-4e89-a9cf-d97a00080b81","ownedRelatedElement":[{"id":"e7292249-00ff-41d1-a8b5-783668e88cc0","eClass":"sysml:AttributeUsage","data":{"declaredName":"minVolume","elementId":"6e6f68f1-9144-46ab-8b05-50d964f904a6","ownedRelationship":[{"id":"4c81d9e3-e5c9-4320-9cb1-395c353a73d1","eClass":"sysml:FeatureValue","data":{"elementId":"f861ccab-1624-4cee-ad26-1dfdc733163c","ownedRelatedElement":[{"id":"8e41e070-5926-4d74-9c76-d727d69d5fde","eClass":"sysml:LiteralRational","data":{"elementId":"d9800108-0bfd-4553-bd4a-ef16d51c1b38","value":10.0}}]}},{"id":"fcbae3ff-aeb7-48b2-97a0-55f8aa446d89","eClass":"sysml:FeatureTyping","data":{"elementId":"17d1e180-0632-4bec-9c10-0b166eb462f0","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"e7292249-00ff-41d1-a8b5-783668e88cc0"}}],"isComposite":true}}]}},{"id":"4c5f7f98-0312-4d3b-b2ac-b5a05fdb5e2f","eClass":"sysml:FeatureMembership","data":{"elementId":"b77a0d5e-7cf2-4978-a622-420c88455097","ownedRelatedElement":[{"id":"d9926727-7378-4177-a940-2fb6c1c89dce","eClass":"sysml:AttributeUsage","data":{"declaredName":"maxVolume","elementId":"c957466a-8bd4-448c-b2e5-545af7d9cadc","ownedRelationship":[{"id":"8f9592ef-9513-4025-ab13-e7d7f822f7d8","eClass":"sysml:FeatureValue","data":{"elementId":"5fd01a42-4bde-4a47-8b52-54a7c60049c1","ownedRelatedElement":[{"id":"a9216e54-f44c-4b1f-b262-13650324d325","eClass":"sysml:OperatorExpression","data":{"elementId":"ba3cea85-2725-4b96-a2af-a9159e84a7a9","ownedRelationship":[{"id":"b88c3a9d-0ce2-426e-a333-77225c45d429","eClass":"sysml:ParameterMembership","data":{"elementId":"4b58a948-936f-4567-9cb5-77739aee17c3","ownedRelatedElement":[{"id":"1ae9086c-60a8-4e6b-a24f-db44e021761b","eClass":"sysml:Feature","data":{"elementId":"19bfc3af-4154-4848-bd2e-59a1754b47df","ownedRelationship":[{"id":"52bad1f8-ee55-4bd5-aa2b-db12ec015c26","eClass":"sysml:FeatureValue","data":{"elementId":"0b26ad14-8872-4a9b-ac55-dac0f189df10","ownedRelatedElement":[{"id":"01ee6181-e890-4277-93fb-4bccf84bf3e6","eClass":"sysml:LiteralRational","data":{"elementId":"eb76a535-cb0d-4efd-b0f7-430b46d85d1a","value":100.0}}]}}],"direction":"in"}}]}},{"id":"8ed9cb6c-2fb5-43af-9bcf-9f2b83ea6e1b","eClass":"sysml:ParameterMembership","data":{"elementId":"c1df91fb-cea4-45f0-80a3-191171afb130","ownedRelatedElement":[{"id":"0222cbc2-571d-41ca-9aa6-5b7128062066","eClass":"sysml:Feature","data":{"elementId":"22361eb7-6a20-4f84-853a-cc4373032846","ownedRelationship":[{"id":"b31231a4-f853-4b71-ace4-eaab66065097","eClass":"sysml:FeatureValue","data":{"elementId":"49b00782-9d36-43a2-8a66-04d1e739daba","ownedRelatedElement":[{"id":"772d1b21-03f3-4299-aac5-564d787129b5","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"74181cea-a48b-4dbc-a45b-878f026c065f","ownedRelationship":[{"id":"576e21f5-e5b3-4a54-b6a7-636f4f2b7034","eClass":"sysml:Membership","data":{"elementId":"ef7b0f68-6c53-4d49-9537-eb3a561b1d91","memberElement":"e7292249-00ff-41d1-a8b5-783668e88cc0"}}]}}]}}],"direction":"in"}}]}}],"operator":"*"}}]}},{"id":"5f49fe65-264b-4773-9aa5-48ed839d4a86","eClass":"sysml:FeatureTyping","data":{"elementId":"c9ba2582-5b2d-4339-a4d9-edf1d05a350c","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"d9926727-7378-4177-a940-2fb6c1c89dce"}}],"isComposite":true}}]}},{"id":"bcb92dbe-1c98-4fbc-89bf-6a420f65d587","eClass":"sysml:FeatureMembership","data":{"elementId":"50960f37-4657-4ff4-9b24-01cf5d4839d5","ownedRelatedElement":[{"id":"7d42ee06-3c27-4eaa-9438-344fc789906a","eClass":"sysml:ConstraintUsage","data":{"declaredName":"pressureLimit","elementId":"0349f315-d32d-43e9-9627-9228da3bb552","ownedRelationship":[{"id":"d40b295e-159f-44fe-84a8-fa114dac3472","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"27e134d7-60b2-4a41-a2eb-ed1ca6c1a119","ownedRelatedElement":[{"id":"faa3b115-5b07-4ecf-9147-0d58ceffaf9c","eClass":"sysml:OperatorExpression","data":{"elementId":"d909007a-ddd7-4e31-b17a-4653dfa8cef8","ownedRelationship":[{"id":"94611d95-3c3d-45a8-813a-3b35933576e0","eClass":"sysml:ParameterMembership","data":{"elementId":"55d9251d-9722-4f1f-ade8-5cce8d7bafb1","ownedRelatedElement":[{"id":"a6e4adef-1a08-4384-880e-95da452d581a","eClass":"sysml:Feature","data":{"elementId":"d1eb3702-b4d0-48d4-90df-5354359f0d33","ownedRelationship":[{"id":"ce942576-087e-4f35-a0a3-7c23a7fe2bb0","eClass":"sysml:FeatureValue","data":{"elementId":"303c1de0-a072-43e8-b687-38527c51eb0e","ownedRelatedElement":[{"id":"83bc616a-bfb5-4777-a169-ac1f8142d2aa","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"046cd544-1c5c-450f-8fac-3077ff9d3652","ownedRelationship":[{"id":"ea9f50bb-2fc9-4934-b613-79a4bdf9ab0f","eClass":"sysml:Membership","data":{"elementId":"8f01928c-b0c1-4056-bfbb-64ca3335b251","memberElement":"15ccc1e3-16b9-4ddf-9959-43141f32d48e"}}]}}]}}],"direction":"in"}}]}},{"id":"7b4f5c1d-fbcd-4074-89bc-6928aecb206f","eClass":"sysml:ParameterMembership","data":{"elementId":"5ac072c4-4955-4803-b651-4d14c001f97e","ownedRelatedElement":[{"id":"41a595a8-9dfb-4542-936b-ba98891a4ea9","eClass":"sysml:Feature","data":{"elementId":"6f135276-6932-4db1-bd9c-126cb8475498","ownedRelationship":[{"id":"fb8829dc-0d44-4004-b7c6-2d617de26808","eClass":"sysml:FeatureValue","data":{"elementId":"73c691d9-1ad0-4357-92ae-8e02e690f5ef","ownedRelatedElement":[{"id":"15f2308f-9b14-4c40-b6a9-d496987dfc8b","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"45435f31-674c-40aa-ad49-ce170852a12b","ownedRelationship":[{"id":"78ed96c8-cc8b-488d-8970-524f4a8bd5be","eClass":"sysml:Membership","data":{"elementId":"5229ec54-8bd3-49e2-8221-a5f8a76142cc","memberElement":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a"}}]}}]}}],"direction":"in"}}]}}],"operator":"<="}}]}}],"isComposite":true}}]}}]}}]}},{"id":"2c772a21-cd4b-472b-b9cb-2d291b86eff3","eClass":"sysml:OwningMembership","data":{"elementId":"2fcf9e17-3424-4677-b324-314c82774361","ownedRelatedElement":[{"id":"3f2124ff-5c56-486b-a296-b1c3476e5180","eClass":"sysml:PartDefinition","data":{"declaredName":"Sensor","elementId":"024ec40b-3a5b-46df-add7-4bcbec5523c7","ownedRelationship":[{"id":"560c46bc-4057-4b9e-8e5a-49e9e4109d05","eClass":"sysml:FeatureMembership","data":{"elementId":"7c0bc2eb-1488-4dd8-8ab9-afadef79a367","ownedRelatedElement":[{"id":"94c0a654-c5dc-4579-a655-89edda340104","eClass":"sysml:AttributeUsage","data":{"declaredName":"label","elementId":"46235c7e-3f38-4dfa-a061-fa5662c9ac1e","ownedRelationship":[{"id":"1758c3f6-d099-452d-8c1b-b375d51491fc","eClass":"sysml:FeatureValue","data":{"elementId":"4d70b01b-05c6-4646-b564-2035f4bde5be","ownedRelatedElement":[{"id":"ec30e68f-b6c2-4ab8-af03-9fea9ceaf2e3","eClass":"sysml:LiteralString","data":{"elementId":"1d905119-2ad9-41e5-8896-7c0d3f166e2b","value":"unnamed"}}]}},{"id":"6fd57c7e-3d50-49b3-94b7-133020804fc4","eClass":"sysml:FeatureTyping","data":{"elementId":"2a1b98bf-116f-44b6-a5cb-8aff68c8e1a8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#76028d3d-69a4-5e12-9002-ce403e0244bd","typedFeature":"94c0a654-c5dc-4579-a655-89edda340104"}}],"isComposite":true}}]}},{"id":"ea09c1cf-a6fb-41a4-9a32-07f9a59d6ef4","eClass":"sysml:FeatureMembership","data":{"elementId":"c23a7f58-2c6b-45c3-bc49-1944baf5face","ownedRelatedElement":[{"id":"edc4f7bc-7d24-498e-8e76-ae1743668254","eClass":"sysml:AttributeUsage","data":{"declaredName":"enabled","elementId":"2aa70e33-7074-4c1d-8ef7-af6874857071","ownedRelationship":[{"id":"8cd41188-d199-4c49-ad23-10e366344c35","eClass":"sysml:FeatureValue","data":{"elementId":"7ea1ae0f-9769-4a93-8523-1b544171ffb4","ownedRelatedElement":[{"id":"5669db5e-ec61-40ca-9a52-8979126921d0","eClass":"sysml:LiteralBoolean","data":{"elementId":"14630a78-98b4-4a46-ac40-c8a49a7b7390","value":true}}]}},{"id":"2afde92b-9d7f-4e1c-ab29-bc9bd2967a82","eClass":"sysml:FeatureTyping","data":{"elementId":"0daf88b8-e462-482b-8220-4f19e3ce8380","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#d1e9242d-b2e3-5270-bf69-4f4fb0447193","typedFeature":"edc4f7bc-7d24-498e-8e76-ae1743668254"}}],"isComposite":true}}]}},{"id":"18f6bc41-fa40-4f81-b741-d601365a37a0","eClass":"sysml:FeatureMembership","data":{"elementId":"2b9522eb-72fb-4e5b-aed4-99209a770f92","ownedRelatedElement":[{"id":"b922024b-5587-4be6-9924-6afa52ce8bf2","eClass":"sysml:AttributeUsage","data":{"declaredName":"samplingRate","elementId":"ddec4b3c-42e0-4d8e-bd99-304def079d94","ownedRelationship":[{"id":"985de5ed-784f-465e-805b-6b7d88b3bddc","eClass":"sysml:FeatureValue","data":{"elementId":"5bb61755-a54e-4ea0-9ec7-e11adf867185","ownedRelatedElement":[{"id":"6d57d690-633a-4018-a0f6-5e732bc16897","eClass":"sysml:LiteralRational","data":{"elementId":"e5ef69e1-5daf-4dae-b0ed-1e7903b3d079","value":100.0}}]}},{"id":"0929e1d2-a563-4e37-befc-02767a3165ea","eClass":"sysml:FeatureTyping","data":{"elementId":"17f59ceb-baef-48a4-b67b-934ed58da6bf","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}],"isComposite":true}}]}},{"id":"48904b34-6744-4d90-8ea3-f8388f930416","eClass":"sysml:FeatureMembership","data":{"elementId":"a7691d9d-0037-4942-8a83-92cc93f14d7d","ownedRelatedElement":[{"id":"2f50920f-47d5-4508-a943-33f9a2d56a23","eClass":"sysml:AttributeUsage","data":{"declaredName":"channelCount","elementId":"4c2b5049-e9d0-4573-8fb7-032cbdcf8fdb","ownedRelationship":[{"id":"14910b2a-ff6e-4f7e-bb13-7e0979c49eca","eClass":"sysml:FeatureValue","data":{"elementId":"2d3e55d0-a26b-4a6b-ac99-f049047ada35","ownedRelatedElement":[{"id":"36055b10-a46d-42c9-95c2-901d02b7490a","eClass":"sysml:LiteralInteger","data":{"elementId":"4525ba90-45e6-4bb4-9a44-a2b3766560e8","value":4}}]}},{"id":"ffed96db-63ef-4e40-b41d-080f7dc68fef","eClass":"sysml:FeatureTyping","data":{"elementId":"c0034730-d919-4a37-ac87-9fc378662a0b","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"2f50920f-47d5-4508-a943-33f9a2d56a23"}}],"isComposite":true}}]}},{"id":"6292da99-b47c-48f9-8d1b-9115b1b0c4e9","eClass":"sysml:FeatureMembership","data":{"elementId":"c7efeeab-923d-42bc-9d62-8bf61c2ab2d7","ownedRelatedElement":[{"id":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9","eClass":"sysml:AttributeUsage","data":{"declaredName":"currentValue","elementId":"855d423f-5dbb-4042-b98c-5a34602b1d0e","ownedRelationship":[{"id":"d9b556a4-b6eb-4e20-90f6-e63908599859","eClass":"sysml:FeatureValue","data":{"elementId":"25fc714d-8228-45f3-98c1-d154cf129985","ownedRelatedElement":[{"id":"ba6195b6-3db6-410a-bf38-a22204c4263e","eClass":"sysml:LiteralRational","data":{"elementId":"31e7ced7-a849-497a-8bea-9e58b3969239"}}],"isInitial":true}},{"id":"0d5731f8-b287-4a2d-854b-32292f6082e2","eClass":"sysml:FeatureTyping","data":{"elementId":"9bb1f845-d859-45d9-b375-8749b0e46272","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}],"isComposite":true}}]}},{"id":"47e0493d-48fd-4a90-977b-f159c2e2dafe","eClass":"sysml:FeatureMembership","data":{"elementId":"7171788a-abcf-4895-8770-192412a650a6","ownedRelatedElement":[{"id":"4d2f8465-d748-4b68-a5a8-d61c03031bd3","eClass":"sysml:AttributeUsage","data":{"declaredName":"errorCount","elementId":"bfc48daf-6923-48f1-9d09-596579985dab","ownedRelationship":[{"id":"c0caf7ee-94b3-44f0-a03b-13c5bfa2f37a","eClass":"sysml:FeatureValue","data":{"elementId":"99cec056-4306-4921-805d-140ecc9ee5de","ownedRelatedElement":[{"id":"0e18cf3c-0d0f-4863-b4e2-407a9fcdad8c","eClass":"sysml:LiteralInteger","data":{"elementId":"cb488158-7555-424f-a37d-1c290aa3cee5"}}],"isInitial":true}},{"id":"96a56407-061b-4f40-81f5-4d8f5e211b56","eClass":"sysml:FeatureTyping","data":{"elementId":"db1c53ba-8888-4645-bbd1-4624a258a238","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"4d2f8465-d748-4b68-a5a8-d61c03031bd3"}}],"isComposite":true}}]}},{"id":"2b4f3de5-32fd-4859-9fe6-5689e017c120","eClass":"sysml:FeatureMembership","data":{"elementId":"24b2ddc3-2007-4fcd-a4b7-943e1bc43948","ownedRelatedElement":[{"id":"3f6b7e75-5039-485c-9fbc-776b772cd746","eClass":"sysml:AttributeUsage","data":{"declaredName":"active","elementId":"251cc6ef-d2c6-4893-941c-076709500c76","ownedRelationship":[{"id":"2ba77e81-8da1-4fdc-ba91-163988a8862a","eClass":"sysml:FeatureValue","data":{"elementId":"457e68ff-f795-4dd9-8643-2dd851d2387a","ownedRelatedElement":[{"id":"0e79ab60-92de-43dc-8aed-85bd61eaa2b7","eClass":"sysml:LiteralBoolean","data":{"elementId":"79052415-268e-41f4-8cf6-ac6484067e91"}}],"isInitial":true}},{"id":"bcd180b6-ecd8-47fc-8f28-08095cd9e23f","eClass":"sysml:FeatureTyping","data":{"elementId":"09b93323-05a1-429c-9dac-dc2672085d02","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#d1e9242d-b2e3-5270-bf69-4f4fb0447193","typedFeature":"3f6b7e75-5039-485c-9fbc-776b772cd746"}}],"isComposite":true}}]}}]}}]}},{"id":"e2cdac2f-1e6c-4a26-b0e9-75e47527ca5d","eClass":"sysml:OwningMembership","data":{"elementId":"c7c6f639-a46a-4360-bc06-4e25c313d91f","ownedRelatedElement":[{"id":"3c20f555-6ccd-448e-a15c-4c249ea54c78","eClass":"sysml:RequirementDefinition","data":{"declaredName":"SensorOperability","elementId":"03e626cf-73bb-4599-995d-b9b3051918cd","ownedRelationship":[{"id":"7be3ea0a-eff4-4a70-86b8-2b1f1d41fa7b","eClass":"sysml:SubjectMembership","data":{"elementId":"a1c897fc-f940-44ff-85b6-39795ec92fc9","ownedRelatedElement":[{"id":"26b28267-29e2-4668-bfb7-eea661577cb7","eClass":"sysml:ReferenceUsage","data":{"declaredName":"s","elementId":"846167d5-277a-4806-a2e6-4ce634cc69ae","ownedRelationship":[{"id":"472f5c5c-3914-4917-87c4-a4384613c261","eClass":"sysml:FeatureTyping","data":{"elementId":"86d37649-f240-4bce-9818-7461c477e982","type":"3f2124ff-5c56-486b-a296-b1c3476e5180","typedFeature":"26b28267-29e2-4668-bfb7-eea661577cb7"}}],"direction":"in","isComposite":true}}]}},{"id":"22084c71-6181-41af-8056-883abc445b79","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"1a9e4a22-4232-483f-8b6b-99eb80f74579","ownedRelatedElement":[{"id":"89b26ac6-c120-44c0-a9e2-437e2f28ddc1","eClass":"sysml:ConstraintUsage","data":{"declaredName":"environmentalPrecondition","elementId":"95a70f5f-b564-4922-8bce-0a84230d07ac","ownedRelationship":[{"id":"03243978-41a3-44ca-94e3-70ffcbb4f56e","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"b6091299-b78a-4249-a9b4-b38de007165f","ownedRelatedElement":[{"id":"f97e3c19-2b5b-4daf-9f0d-017fe9f962f7","eClass":"sysml:OperatorExpression","data":{"elementId":"f33ab7c6-5006-4de8-b53a-62dc5fc24325","ownedRelationship":[{"id":"b5562f52-e2ce-4d03-8ed3-7b95ea472194","eClass":"sysml:ParameterMembership","data":{"elementId":"c44bf22b-24cd-42bd-aadf-e857271935b2","ownedRelatedElement":[{"id":"9fd3acc6-0c9e-4d89-ab4a-d58627712cb3","eClass":"sysml:Feature","data":{"elementId":"f7c53edb-8c09-4124-ae5d-96c5238f5d2e","ownedRelationship":[{"id":"3cf505dd-61d8-43da-b52e-84d73e9348ca","eClass":"sysml:FeatureValue","data":{"elementId":"ca481874-8b4a-482b-9f84-078ab69c83b9","ownedRelatedElement":[{"id":"f23fd077-7725-426f-924a-85a00a0ea779","eClass":"sysml:OperatorExpression","data":{"elementId":"bf6bd6fe-047b-456d-ba8c-92f8ffb5deba","ownedRelationship":[{"id":"e5099d7a-6a81-4061-b507-5ef72d7933f0","eClass":"sysml:ParameterMembership","data":{"elementId":"51cd9462-617c-4179-a552-eea9e8c766a4","ownedRelatedElement":[{"id":"17daf4fb-22ee-4a70-a84f-63a09ccee784","eClass":"sysml:Feature","data":{"elementId":"e880c32a-6ed3-498a-aeb4-d32250bcc061","ownedRelationship":[{"id":"3a586119-f53f-40f1-9fae-4b2e29a6e57e","eClass":"sysml:FeatureValue","data":{"elementId":"f22c0876-8374-4eca-ad79-d1d7053c88a4","ownedRelatedElement":[{"id":"d31bb8ba-e377-4983-bfc0-ed58e89d54f8","eClass":"sysml:FeatureChainExpression","data":{"elementId":"fe4bac6d-b31c-4a49-97b8-75ac2b853ab9","ownedRelationship":[{"id":"35bd3dc6-5510-49ec-ae49-8b5d11f27578","eClass":"sysml:ParameterMembership","data":{"elementId":"3b28eb00-c108-491d-a39f-97dd584fc5b3","ownedRelatedElement":[{"id":"75251a12-c877-4043-8ea4-0c7953c073fc","eClass":"sysml:Feature","data":{"elementId":"8070b6d4-13e9-42e9-bd09-95f4f0168623","ownedRelationship":[{"id":"0bf3106a-9de8-492a-86ef-6c37d1a870ab","eClass":"sysml:FeatureValue","data":{"elementId":"d376ea9b-17ac-4eea-961b-cd0d59ab38fe","ownedRelatedElement":[{"id":"46af9d73-20cb-470a-9914-53f136e2eb36","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"e1665ec4-a3c1-417a-ba5b-6778561f9fc0","ownedRelationship":[{"id":"ddeb93ce-38fa-4474-895f-e58832028e14","eClass":"sysml:Membership","data":{"elementId":"80218b82-c542-40a4-a20c-c413faa628da","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"0adca218-7d4b-4068-8ab5-7f324f83dc5e","eClass":"sysml:Membership","data":{"elementId":"087cc752-6838-47d8-aa38-d88990a35a70","memberElement":"edc4f7bc-7d24-498e-8e76-ae1743668254"}}]}}]}}],"direction":"in"}}]}},{"id":"2d487599-d100-47a2-9f9d-60f4e3c7effd","eClass":"sysml:ParameterMembership","data":{"elementId":"43fecf2d-ee36-4680-9295-cf4cdf6e5e82","ownedRelatedElement":[{"id":"5c057fe8-07d0-4a61-8aa1-155a9870b97a","eClass":"sysml:Feature","data":{"elementId":"d8e6c10f-3ced-40a5-becd-286d7a1e5e2d","ownedRelationship":[{"id":"c7926f63-0e5a-4abf-9f05-d3f7ede1df40","eClass":"sysml:FeatureValue","data":{"elementId":"a1742093-8ec5-4438-a7a3-ffea0821efd3","ownedRelatedElement":[{"id":"daaecec2-38f8-470f-92be-4e76742d5bdc","eClass":"sysml:LiteralBoolean","data":{"elementId":"3c8b2228-7d6d-45ba-bfd1-3a80983c13fb","value":true}}]}}],"direction":"in"}}]}}],"operator":"=="}}]}}],"direction":"in"}}]}},{"id":"f9ec458e-862b-45a2-b4f7-ae808551b406","eClass":"sysml:ParameterMembership","data":{"elementId":"67d15eef-d95a-4262-a3d7-ac8c73f37966","ownedRelatedElement":[{"id":"aac0f2a4-f51a-41b0-ab00-d77e005ba716","eClass":"sysml:Feature","data":{"elementId":"e0346753-1dfc-4ec3-b0aa-d670b6e6b5ee","ownedRelationship":[{"id":"a635c6f5-4992-4560-8df6-4cf94e9678fe","eClass":"sysml:FeatureValue","data":{"elementId":"825de020-d7cf-4539-a128-36e9ef1ccba4","ownedRelatedElement":[{"id":"a3087e8f-fc12-4e29-b108-9c9debcedd1e","eClass":"sysml:OperatorExpression","data":{"elementId":"093dc3ba-ae58-4d39-94be-e04dd6d55396","ownedRelationship":[{"id":"51f5bb92-e99e-4a13-89eb-414ce7331c77","eClass":"sysml:ParameterMembership","data":{"elementId":"b9d31569-e464-4f5c-8deb-6bf749306271","ownedRelatedElement":[{"id":"e91251cd-8d24-4c11-b777-550b6147ae63","eClass":"sysml:Feature","data":{"elementId":"606a4d32-c5ac-4276-9015-45c24fd27779","ownedRelationship":[{"id":"afeff4b6-1d9a-441d-a692-a527f60625f0","eClass":"sysml:FeatureValue","data":{"elementId":"32569bac-9960-4873-8a55-50899cbfb2fb","ownedRelatedElement":[{"id":"1800b695-f852-4f75-b124-7086083ef9a9","eClass":"sysml:FeatureChainExpression","data":{"elementId":"42680337-a1c6-4445-a6e6-571aab4ea27e","ownedRelationship":[{"id":"341cbae7-5abe-4fb9-80f4-a647450fcf31","eClass":"sysml:ParameterMembership","data":{"elementId":"cded185e-f09f-4c95-9802-b25d02fa97f7","ownedRelatedElement":[{"id":"36c40f15-53d9-4da0-bba9-7097c2b14972","eClass":"sysml:Feature","data":{"elementId":"b20c603d-d30e-41a2-a81f-d27c5603a17e","ownedRelationship":[{"id":"02a48840-7c5a-47da-b726-76152b533eb7","eClass":"sysml:FeatureValue","data":{"elementId":"fbe218e1-dcca-4266-8df8-ef8d20ff4d98","ownedRelatedElement":[{"id":"1acc5b62-4d4a-40d7-b92c-bbcc5acea29e","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"2b9347c6-9600-422b-bd62-f504a00c1690","ownedRelationship":[{"id":"d89b10dd-9b95-49ec-8acb-41a135c3359d","eClass":"sysml:Membership","data":{"elementId":"95a02965-4d2b-4766-a29b-bcc42f863d6d","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"ae0a3065-f5ec-4168-9be2-9816bb3a84a0","eClass":"sysml:Membership","data":{"elementId":"8919a2b6-9784-453e-abf2-940fb136e4d2","memberElement":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}]}}]}}],"direction":"in"}}]}},{"id":"6720a737-26ee-4583-865a-66f1d30e2119","eClass":"sysml:ParameterMembership","data":{"elementId":"9e51fe6d-89dd-4911-854a-825f35355b80","ownedRelatedElement":[{"id":"001b01d8-02c0-4f02-851f-b9baeb0465a6","eClass":"sysml:Feature","data":{"elementId":"df7244c0-cfea-4b87-b5e6-3131be5b7abf","ownedRelationship":[{"id":"c1f7d964-fd30-4ebd-b0a5-dc0937c013fe","eClass":"sysml:FeatureValue","data":{"elementId":"782a1e9c-878d-447d-a0d0-6a865c708f8e","ownedRelatedElement":[{"id":"8ebe7473-9ea1-4965-8a43-a4c1b7ff3ead","eClass":"sysml:LiteralRational","data":{"elementId":"7f088100-1afb-402f-9cba-5976381966ef"}}]}}],"direction":"in"}}]}}],"operator":">"}}]}}],"direction":"in"}}]}}],"operator":"&"}}]}}],"isComposite":true}}]}},{"id":"fd89f7d5-d5e4-4090-b71f-7b7edc56f820","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"9132678c-8721-4d13-9c1b-6421f10b9fa7","ownedRelatedElement":[{"id":"43818255-7ffb-4ef9-ad34-603c623a0a44","eClass":"sysml:ConstraintUsage","data":{"declaredName":"noInitialErrors","elementId":"ec6684fe-fe49-4b1d-8597-8db46655170a","ownedRelationship":[{"id":"305f2777-fc7c-47cb-b077-95c960fcaef7","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"4e0495c2-a1b1-4f0f-b505-b77a1e09fe91","ownedRelatedElement":[{"id":"674bd9db-8e8f-40a5-afbb-42602be3f4b1","eClass":"sysml:OperatorExpression","data":{"elementId":"74a13c5e-2b68-4aac-ac54-58940cac49a8","ownedRelationship":[{"id":"0fd5a82f-02b2-453f-ae3d-404b44d923a2","eClass":"sysml:ParameterMembership","data":{"elementId":"75dfe7c0-47f2-458f-bc4d-61692f7039b6","ownedRelatedElement":[{"id":"9b0f0b70-d567-42c4-b3de-042256e9f877","eClass":"sysml:Feature","data":{"elementId":"22528542-1576-44a2-85c4-9a278e5af324","ownedRelationship":[{"id":"ffe8010f-e97a-43f4-8f76-634d2d3a4a1c","eClass":"sysml:FeatureValue","data":{"elementId":"2a9edcb9-a96c-432b-87a9-af56ce864c5c","ownedRelatedElement":[{"id":"5b482eaf-c916-4953-8a82-8c6c9f36481c","eClass":"sysml:FeatureChainExpression","data":{"elementId":"fa6b2042-eef7-408c-b5d3-8a5094eec9e3","ownedRelationship":[{"id":"322ad996-7446-413a-8b00-fe0a39e53dea","eClass":"sysml:ParameterMembership","data":{"elementId":"6ec90405-8ae3-43b4-b295-1b0af8e3cdfe","ownedRelatedElement":[{"id":"b5b22abf-5a4f-4d1b-940f-f9ffd76cc274","eClass":"sysml:Feature","data":{"elementId":"2fc69bcb-4408-4e6b-8d37-6e2509a0f707","ownedRelationship":[{"id":"b6257642-230e-4847-815e-2dc125933313","eClass":"sysml:FeatureValue","data":{"elementId":"e58838f0-f500-4ce3-9b28-1cb05ab6c0ab","ownedRelatedElement":[{"id":"ab026b01-c127-4f2e-af15-6232d7453a0b","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"426b9f08-b36d-424d-ae1c-72e19f089688","ownedRelationship":[{"id":"ee54e3cf-6459-441c-b58f-d31278a72ecb","eClass":"sysml:Membership","data":{"elementId":"595198d2-7c69-40b2-9606-0f87f250e701","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"5d654f07-ff8c-411a-9339-290f4b364f52","eClass":"sysml:Membership","data":{"elementId":"2f356da4-c6d7-4281-aed5-5074486d209f","memberElement":"4d2f8465-d748-4b68-a5a8-d61c03031bd3"}}]}}]}}],"direction":"in"}}]}},{"id":"6c32c3c0-8ecf-4bd8-92b2-0637b65689bf","eClass":"sysml:ParameterMembership","data":{"elementId":"af68c65d-a92e-44ec-b189-ec2f6aefaae2","ownedRelatedElement":[{"id":"d4cbf635-a286-4a5a-a240-46e56902b2e7","eClass":"sysml:Feature","data":{"elementId":"d7de254e-2bc4-4857-bc91-eb2488f9fa82","ownedRelationship":[{"id":"6209d9f9-68a3-4b82-a6b9-751127988355","eClass":"sysml:FeatureValue","data":{"elementId":"d8c0c7be-09d7-4dad-8ccb-7dd06b358f00","ownedRelatedElement":[{"id":"7a0f2b0f-3843-41c5-b88f-90cee6e079b9","eClass":"sysml:LiteralInteger","data":{"elementId":"1c8e5633-07ae-47b2-852e-620bdfc728cc"}}]}}],"direction":"in"}}]}}],"operator":"=="}}]}}],"isComposite":true}}]}},{"id":"1015f3d7-efa6-4de1-b045-446b4186c2f2","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"7c3fdec2-1586-426d-903b-10d1fa9b388b","ownedRelatedElement":[{"id":"744de1e8-a545-4d5f-9c22-0b5a077f6d16","eClass":"sysml:ConstraintUsage","data":{"declaredName":"samplingInBounds","elementId":"710c2d73-2c5e-4aaf-a2f2-0e0cedb31d52","ownedRelationship":[{"id":"0d5711b7-29a8-4e88-9c96-6b98678b32a9","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"8c4d2994-52bd-4fec-9528-2f14b2e3a550","ownedRelatedElement":[{"id":"fb8ef886-b55a-43d0-bf93-0a67b2426fb9","eClass":"sysml:OperatorExpression","data":{"elementId":"0a64137e-061e-47e0-a371-ee0d95490567","ownedRelationship":[{"id":"1eeb9c5e-cc00-4f7d-ab0b-835faaddbad9","eClass":"sysml:ParameterMembership","data":{"elementId":"82a132ad-0499-45ed-ba57-f80116752617","ownedRelatedElement":[{"id":"1ce0a55e-ef7d-46c5-801c-639df3264258","eClass":"sysml:Feature","data":{"elementId":"5e66ffe4-195f-4c13-afee-ed4f0164cbf3","ownedRelationship":[{"id":"7e2410ff-1fc4-40bc-8a1f-f67cd3380704","eClass":"sysml:FeatureValue","data":{"elementId":"68322213-a33f-4ac1-a1e9-e5bcfa153489","ownedRelatedElement":[{"id":"4dc3b7ac-ed2b-4b07-ac88-d1b0b0174946","eClass":"sysml:OperatorExpression","data":{"elementId":"cc836d15-6462-49f6-90d6-3e1fe85d57f5","ownedRelationship":[{"id":"ab468039-0014-4e6f-b1a4-d8cd92370649","eClass":"sysml:ParameterMembership","data":{"elementId":"3478fa32-bda9-48ae-b44d-4d8e1a8b745b","ownedRelatedElement":[{"id":"dc1b31db-45df-48c3-bf0c-0925a5ce11f9","eClass":"sysml:Feature","data":{"elementId":"4dbe01b8-e406-48f9-878e-b1925d0b94bf","ownedRelationship":[{"id":"178fe70f-8113-4e4e-aaa0-e23253640576","eClass":"sysml:FeatureValue","data":{"elementId":"86f7f3a3-d8e8-415b-a284-a9e744b42abe","ownedRelatedElement":[{"id":"56645ba2-6aef-4a6a-a66e-8191b5c87dbf","eClass":"sysml:FeatureChainExpression","data":{"elementId":"6514848e-8123-44b8-9acc-7f9d9db8cb8b","ownedRelationship":[{"id":"ec6dda59-1e10-4ed6-ad3d-7114fd5e09cd","eClass":"sysml:ParameterMembership","data":{"elementId":"b17edd31-837e-4a66-a9f9-d92e0da08a62","ownedRelatedElement":[{"id":"17f67cfc-824a-4aeb-bd36-999ec420d783","eClass":"sysml:Feature","data":{"elementId":"d83c9b8b-ad1e-4add-b43c-aebddbd54243","ownedRelationship":[{"id":"855f40bf-bca7-4599-aef6-e58ae1249a5b","eClass":"sysml:FeatureValue","data":{"elementId":"97b6dc0b-a32e-4d9d-b40b-3a37d0143b19","ownedRelatedElement":[{"id":"13182f23-36f8-4335-8756-fe068510f668","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"1c0f3f4e-7e52-417a-8e2c-28958a350b43","ownedRelationship":[{"id":"10ec6e74-d315-470d-838c-ee910f4a56a5","eClass":"sysml:Membership","data":{"elementId":"e312bc35-8594-4a20-8ff7-c101dc2090fd","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"fcbae642-5dfa-414e-91ff-2106f907a48e","eClass":"sysml:Membership","data":{"elementId":"7f68ad69-159f-4675-9f02-35da9cba4740","memberElement":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}]}}]}}],"direction":"in"}}]}},{"id":"d0e9d92c-225b-462e-a99b-394b2895b660","eClass":"sysml:ParameterMembership","data":{"elementId":"5c481b3a-ec1b-4fc1-9f9f-900c59712400","ownedRelatedElement":[{"id":"9df55992-f8c4-4ebc-9589-486477e856de","eClass":"sysml:Feature","data":{"elementId":"77f13915-1767-44f3-9711-cc035cf30882","ownedRelationship":[{"id":"8252fef3-a39c-4990-842a-495495cbffcc","eClass":"sysml:FeatureValue","data":{"elementId":"d74880a1-050c-4b54-a015-c38e1b1451c9","ownedRelatedElement":[{"id":"40f6c556-0ae7-47a9-b845-6217b18a624e","eClass":"sysml:LiteralRational","data":{"elementId":"1983f1ed-8ecf-4faa-9f62-3c12e2af44cf","value":1.0}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"direction":"in"}}]}},{"id":"02abeed7-427a-46aa-8a22-5b9cbb4ece78","eClass":"sysml:ParameterMembership","data":{"elementId":"a0bb41de-1d00-4001-8d5f-595698159369","ownedRelatedElement":[{"id":"3e5d55cb-dcb1-4fc5-9aa4-2d11e2a737e1","eClass":"sysml:Feature","data":{"elementId":"c663de85-1135-4e49-b3a9-e08ad8f18d46","ownedRelationship":[{"id":"3e84f11c-cb4a-4e34-bfb4-60ce73072d4f","eClass":"sysml:FeatureValue","data":{"elementId":"90242b82-6b90-48eb-9e79-7ae21c2405b3","ownedRelatedElement":[{"id":"0dbf27e7-d9a3-4dde-b801-c8ba92ecaf67","eClass":"sysml:OperatorExpression","data":{"elementId":"9f79e4e0-5f49-44e4-9336-bd6c6600deb3","ownedRelationship":[{"id":"b4015705-c1e1-4630-9892-ca94207213a3","eClass":"sysml:ParameterMembership","data":{"elementId":"8b7a8b36-4faa-4241-9af4-7119e2ea978f","ownedRelatedElement":[{"id":"863bc422-95cb-4321-adaf-4e7c202d3ac0","eClass":"sysml:Feature","data":{"elementId":"605bf947-1c79-4920-8f35-bb22cc84d3e8","ownedRelationship":[{"id":"b8ff86a1-8074-4ceb-9943-234263d0ab0a","eClass":"sysml:FeatureValue","data":{"elementId":"45f79d0d-eb20-449e-b0a1-0578ac65ee3a","ownedRelatedElement":[{"id":"65527d7d-d7b5-4a89-91b4-7ef154a4c8c5","eClass":"sysml:FeatureChainExpression","data":{"elementId":"6aef4085-719f-47b5-8d52-3aacdcb46cff","ownedRelationship":[{"id":"f97d2edd-e85b-49b3-ae3d-ed59c67efc20","eClass":"sysml:ParameterMembership","data":{"elementId":"4740471e-5432-4b9f-a8c4-7fcb0d3bab9e","ownedRelatedElement":[{"id":"ac4bf947-176f-4872-9539-9d558cb9f4d4","eClass":"sysml:Feature","data":{"elementId":"d32ac236-1b32-483a-bbc5-0363583dfaab","ownedRelationship":[{"id":"c1a41a4b-2a5f-4503-8433-c6d57a309dbd","eClass":"sysml:FeatureValue","data":{"elementId":"16ce4186-e717-40bc-9b42-b7abe98c5722","ownedRelatedElement":[{"id":"0332b5da-304d-4b3b-a128-be7ac0e4db43","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"2e1db3c1-d2ab-4651-a8b5-91bf0e9efafc","ownedRelationship":[{"id":"bf180bff-3dac-451d-ac17-3f1f95a44212","eClass":"sysml:Membership","data":{"elementId":"c2dec826-b8ba-4744-9c32-ba0a98d8a050","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"104e5faf-4077-4efd-8cf2-fff17b6ac41f","eClass":"sysml:Membership","data":{"elementId":"4f5fe8c1-3da6-4e47-bf81-c1b89cf293c9","memberElement":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}]}}]}}],"direction":"in"}}]}},{"id":"b14481fe-2a63-4932-98e3-54a57dad9118","eClass":"sysml:ParameterMembership","data":{"elementId":"9e944981-882f-4340-a990-ef9b0d040bbb","ownedRelatedElement":[{"id":"7aab7c53-21c2-4d79-8216-4f01191a9f34","eClass":"sysml:Feature","data":{"elementId":"fb8fe825-cee3-48dd-8603-bac9fc6b67a5","ownedRelationship":[{"id":"86f1647e-66a1-4482-ba36-485f4663f643","eClass":"sysml:FeatureValue","data":{"elementId":"14cb76eb-886f-4221-9250-bcc0b8b6c81a","ownedRelatedElement":[{"id":"4425218f-1718-455d-9e86-81a82c6b1f3f","eClass":"sysml:LiteralRational","data":{"elementId":"e6bfe9d8-01b1-4b40-8645-182732d2c796","value":10000.0}}]}}],"direction":"in"}}]}}],"operator":"<="}}]}}],"direction":"in"}}]}}],"operator":"&"}}]}}],"isComposite":true}}],"kind":"requirement"}},{"id":"13b6da3e-7222-4755-a0db-73ab0e7cef43","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"74e11b1f-78ff-4a64-98d2-8d9f206f5345","ownedRelatedElement":[{"id":"5430a222-7a32-41d9-bff7-f3437bfb2541","eClass":"sysml:ConstraintUsage","data":{"declaredName":"stableOutput","elementId":"78954a81-8ed8-4abb-94e5-260396996d8c","ownedRelationship":[{"id":"9bdf03b3-0eef-46b2-b407-ea5942872033","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"7eeee652-e8b0-4b38-be9b-cbbc02d9d2b6","ownedRelatedElement":[{"id":"e2a16041-e92b-4352-a11f-e934e3f77244","eClass":"sysml:OperatorExpression","data":{"elementId":"162b90b8-ac96-4326-a8fc-e541d38f7ea5","ownedRelationship":[{"id":"2bb34634-e23e-4e36-af6d-4a4135a1da3e","eClass":"sysml:ParameterMembership","data":{"elementId":"50ee9282-e9d8-4055-b96c-e14a15715951","ownedRelatedElement":[{"id":"0d02bb77-2368-4995-b01d-f9767c18f91c","eClass":"sysml:Feature","data":{"elementId":"5b6a39a6-ba11-4b57-9e29-37d4c5d062ee","ownedRelationship":[{"id":"50730cce-15f8-41ec-b73f-373406c56ad3","eClass":"sysml:FeatureValue","data":{"elementId":"4e6818ae-48cc-48e2-b924-93006bded6d1","ownedRelatedElement":[{"id":"6457b597-51ee-43d3-b47a-d6185b962d52","eClass":"sysml:OperatorExpression","data":{"elementId":"1c19c360-b9a3-4c40-ac36-f4307bb173ec","ownedRelationship":[{"id":"87d2c594-9d82-4eee-afbd-da23103c7bce","eClass":"sysml:ParameterMembership","data":{"elementId":"4be4a607-9609-4c3d-ba9f-8a4ef5272115","ownedRelatedElement":[{"id":"c84d00e0-8a5d-420c-93d0-426f57ae9bff","eClass":"sysml:Feature","data":{"elementId":"ac7d8f05-80d1-42dc-a844-c29f0a3c8165","ownedRelationship":[{"id":"05c17c5f-82e5-47a2-92ec-60c73c48e28c","eClass":"sysml:FeatureValue","data":{"elementId":"46806968-3ec7-4de2-ba39-22a3da992209","ownedRelatedElement":[{"id":"ca61c2d5-59fd-42ea-903a-130686e54e4e","eClass":"sysml:FeatureChainExpression","data":{"elementId":"2f496fa4-27db-45bc-8866-6dab5894dc7e","ownedRelationship":[{"id":"f5ad2a2c-0e3e-4a42-8dae-b26d4acd689d","eClass":"sysml:ParameterMembership","data":{"elementId":"02caa747-a770-4bb4-8996-4dd84116ec63","ownedRelatedElement":[{"id":"c925544f-75ce-4ca2-8a5b-73ec1da5876e","eClass":"sysml:Feature","data":{"elementId":"97535996-cbed-448d-a316-57100f9c3f93","ownedRelationship":[{"id":"c2607860-5083-4aef-8014-135d7bb0bd5c","eClass":"sysml:FeatureValue","data":{"elementId":"e2228dbe-f53b-4aa8-b3ea-545291c3d6df","ownedRelatedElement":[{"id":"d5de3a0c-27c9-453b-b6c9-9b71a2badddc","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"08c644d4-4b03-4009-a5e5-3d38837a2c66","ownedRelationship":[{"id":"fb070d5a-358b-4d86-9271-98ecf17af4f9","eClass":"sysml:Membership","data":{"elementId":"4bc3df72-8616-469d-ad93-3937b185dc79","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"f2886c92-7a40-44fd-b80a-fd9e66bf295d","eClass":"sysml:Membership","data":{"elementId":"bd803489-0cab-42a9-abdf-f3653adb4f63","memberElement":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}]}}]}}],"direction":"in"}}]}},{"id":"592bb152-0628-4587-b6da-1babfb6a4899","eClass":"sysml:ParameterMembership","data":{"elementId":"76ddca74-30e9-4d15-ad76-fc1ddc2520b2","ownedRelatedElement":[{"id":"3ce88764-e833-46f1-90f3-bfe64ce8fd65","eClass":"sysml:Feature","data":{"elementId":"c70d7936-c85b-42c8-b0c1-ccf8f5d30c21","ownedRelationship":[{"id":"5c224c44-af1e-49f3-b965-210e58d2cf15","eClass":"sysml:FeatureValue","data":{"elementId":"0d6a2d4f-ae7c-4089-9272-85dff9c776e1","ownedRelatedElement":[{"id":"06924b07-5194-4335-ac55-11054257b115","eClass":"sysml:OperatorExpression","data":{"elementId":"aa88b9d7-0fca-4991-967d-cdfed6b3e2ea","ownedRelationship":[{"id":"4b5ef4d7-92e0-4402-bb6f-96f74483d2ca","eClass":"sysml:ParameterMembership","data":{"elementId":"d1595baa-e83d-44aa-8410-68705291932e","ownedRelatedElement":[{"id":"3c2c1075-8ff7-4d04-83ad-4e64990a60ea","eClass":"sysml:Feature","data":{"elementId":"caa645a9-d5a4-465a-bdf5-51c86fa9865f","ownedRelationship":[{"id":"28697868-fc54-4ed3-8027-1667d4eb550b","eClass":"sysml:FeatureValue","data":{"elementId":"0afe35e7-67d5-48f2-a0dc-5f8ba0c88941","ownedRelatedElement":[{"id":"dbb371b6-8314-403a-b45c-fcbea954bfaa","eClass":"sysml:LiteralRational","data":{"elementId":"49bfa9b9-2fec-44ec-bdaa-c1d1fa197d5c","value":1000.0}}]}}],"direction":"in"}}]}}],"operator":"-"}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"direction":"in"}}]}},{"id":"9061073e-f8c8-4cc6-9064-303071dcfea0","eClass":"sysml:ParameterMembership","data":{"elementId":"2e0797de-4bab-4855-8c06-c56c54cf5735","ownedRelatedElement":[{"id":"0aadea47-f0cf-4ef7-9f2b-e61a0ee9cbd7","eClass":"sysml:Feature","data":{"elementId":"8449c67b-26a9-4ee8-a3a1-2e1adb96c980","ownedRelationship":[{"id":"afa68833-3809-4200-abc6-8ad5e6ae7657","eClass":"sysml:FeatureValue","data":{"elementId":"a086a6c5-8d87-437e-9b24-7305389bae35","ownedRelatedElement":[{"id":"aea8971f-abff-401f-b81c-96e82ded07ba","eClass":"sysml:OperatorExpression","data":{"elementId":"9ef4ebbe-09c8-4af7-88f3-713d66115c5c","ownedRelationship":[{"id":"6f815ed1-4211-4dc0-a79e-e0557d93c6e7","eClass":"sysml:ParameterMembership","data":{"elementId":"5b55cf36-a0bb-43d5-83a9-6fed193bb3c6","ownedRelatedElement":[{"id":"fc0e0ff2-97c1-4ee3-be70-96d783c300f3","eClass":"sysml:Feature","data":{"elementId":"4cc2d2c6-d8f9-4903-af9c-35d0732ba1ec","ownedRelationship":[{"id":"93fd7287-17c7-438f-8d4a-98d85c36ca0b","eClass":"sysml:FeatureValue","data":{"elementId":"8c006f9f-34c6-4f01-9238-3c8db61fff24","ownedRelatedElement":[{"id":"0147be8c-d4d1-4ce6-8cfd-c67be64a4ea5","eClass":"sysml:FeatureChainExpression","data":{"elementId":"e58e7aae-3384-4534-9b9e-ff145d305049","ownedRelationship":[{"id":"3e8ef9ad-5952-44e3-ba6f-1e2f0220e723","eClass":"sysml:ParameterMembership","data":{"elementId":"e31ece95-3cb1-481c-9c88-cef2a99755bd","ownedRelatedElement":[{"id":"7b911b07-3b0b-41f0-8228-a5b5904132ec","eClass":"sysml:Feature","data":{"elementId":"766277b4-ff73-477c-ace3-91e98f09afa4","ownedRelationship":[{"id":"b0669556-a14c-4c44-b187-e36f7ab247f2","eClass":"sysml:FeatureValue","data":{"elementId":"a08b25ec-f69a-406d-8ab6-fcf60b5a7c79","ownedRelatedElement":[{"id":"d40caf8d-5643-4874-8f1a-85454b0a6a96","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"3fb26596-7403-4534-a34e-c470eb196ba3","ownedRelationship":[{"id":"2d661746-ba83-4edf-9f05-ee4ae4d2d147","eClass":"sysml:Membership","data":{"elementId":"9386c8fd-497a-49f0-86cd-e705cce8e016","memberElement":"26b28267-29e2-4668-bfb7-eea661577cb7"}}]}}]}}],"direction":"in"}}]}},{"id":"e945de86-7654-4a0f-8f9f-419fb2539a70","eClass":"sysml:Membership","data":{"elementId":"df8e42c4-9d75-4807-8590-97a9f3e118df","memberElement":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}]}}]}}],"direction":"in"}}]}},{"id":"d908598b-b102-45e2-8607-791d3785936c","eClass":"sysml:ParameterMembership","data":{"elementId":"94d09dbb-d0ff-40d7-b495-6ca152a8f689","ownedRelatedElement":[{"id":"09cf2f87-4b62-4b48-b431-ec3a9606162f","eClass":"sysml:Feature","data":{"elementId":"5b25b441-dbaa-471c-a034-3e28ef3328ea","ownedRelationship":[{"id":"c048582f-5c86-42bc-83f6-0fd41c208999","eClass":"sysml:FeatureValue","data":{"elementId":"772bfeb3-315a-45ac-97f4-b965ecab8d02","ownedRelatedElement":[{"id":"951b914d-f33b-4028-a731-98cbb9282f2f","eClass":"sysml:LiteralRational","data":{"elementId":"a9a07aae-af6e-400b-8ec6-6c307ef005f9","value":1000.0}}]}}],"direction":"in"}}]}}],"operator":"<="}}]}}],"direction":"in"}}]}}],"operator":"&"}}]}}],"isComposite":true}}],"kind":"requirement"}}]}}]}},{"id":"0f77318f-48df-4fd5-b4fe-c2470070695a","eClass":"sysml:OwningMembership","data":{"elementId":"3f6dda74-d5cc-4bc5-b728-79fd8dc7a929","ownedRelatedElement":[{"id":"2efcf5d4-4948-4b7d-b779-f3f694eb8165","eClass":"sysml:StateDefinition","data":{"declaredName":"ThermalControl","elementId":"040718ea-26b5-47d6-ba84-9f7c43fe2c07","ownedRelationship":[{"id":"6bd335ce-5089-4089-902f-917b1b6fed36","eClass":"sysml:StateSubactionMembership","data":{"elementId":"ded89b53-c1f0-4c68-8a56-d7283bc2b862","ownedRelatedElement":[{"id":"ac85c0b8-2d5a-491f-81dc-fb9b09b3ab31","eClass":"sysml:ActionUsage","data":{"elementId":"fd138068-384e-4be8-b885-ef3b218e006f","isComposite":true}}],"kind":"entry"}},{"id":"0345c054-7f57-45ec-8473-1261313b14d6","eClass":"sysml:FeatureMembership","data":{"elementId":"ea20286f-4020-4488-bfdd-f8b8c0293486","ownedRelatedElement":[{"id":"0a63014b-116e-455e-85f5-bc66c922d691","eClass":"sysml:TransitionUsage","data":{"elementId":"ddef46f5-05d7-411e-b826-3f1f3fea21ff","ownedRelationship":[{"id":"baa2a68d-e8f5-470c-b497-eda44fe94d59","eClass":"sysml:Membership","data":{"elementId":"0ea170b2-1597-4c55-b3e8-6cf8b7a9d204","memberElement":"ac85c0b8-2d5a-491f-81dc-fb9b09b3ab31"}},{"id":"0e6d29f8-3a63-48d1-af12-339e173ae602","eClass":"sysml:OwningMembership","data":{"elementId":"f5f627e0-538f-4fd9-b64b-a14966f22482","ownedRelatedElement":[{"id":"c59c0174-da0a-4972-a5ca-6743ab295651","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"f55e815c-45ae-4320-9753-a362b3c8e6e5","ownedRelationship":[{"id":"38f392ae-b052-4618-8c6d-8c01e635a521","eClass":"sysml:EndFeatureMembership","data":{"elementId":"8f15832d-752e-417c-a176-520904b7dfe1","ownedRelatedElement":[{"id":"a2b00582-c35c-41cf-86c2-49ab6a853807","eClass":"sysml:ReferenceUsage","data":{"elementId":"293900dd-1f99-49d4-8638-8c541b96ed6b","isEnd":true}}]}},{"id":"bf9eb61a-6c2d-4a2e-af99-6aec971b7e95","eClass":"sysml:EndFeatureMembership","data":{"elementId":"067cb51a-1f7b-40ad-b4e2-12b298e85ccc","ownedRelatedElement":[{"id":"76806c6d-2d0a-4dc0-9e1c-23dfe0845699","eClass":"sysml:ReferenceUsage","data":{"elementId":"7413373c-e4ea-4187-bcbe-e4f93128dab3","ownedRelationship":[{"id":"e57840d9-94d8-4186-8bbc-e56d0b5532d9","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"2a9d2963-2b80-4ed3-8daf-6b3637ed343c","subsettingFeature":"76806c6d-2d0a-4dc0-9e1c-23dfe0845699","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"1912dc94-522f-4d2a-9b1b-84ca3d86491e","eClass":"sysml:ParameterMembership","data":{"elementId":"4c276cae-1333-4c4d-a0fc-609b74b86cd6","ownedRelatedElement":[{"id":"43bed746-a5d8-4961-9fa3-560b9e53d921","eClass":"sysml:ReferenceUsage","data":{"elementId":"9e08b023-69df-4262-92be-ce2b9c6339a0","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"560d42e6-c398-48cf-9816-1bd9cae87041","eClass":"sysml:FeatureMembership","data":{"elementId":"4b970e61-3c84-4cf2-9c1f-ea3ef53bb346","ownedRelatedElement":[{"id":"630f2641-b66a-4f52-91c6-057b1c5811d0","eClass":"sysml:StateUsage","data":{"declaredName":"normal","elementId":"59276fa3-50b8-45da-a7d0-1775b3632476","isComposite":true}}]}},{"id":"e1a46bc4-adad-4ecd-ac1f-ec293b4466da","eClass":"sysml:FeatureMembership","data":{"elementId":"ca2e7bf0-9cee-4679-b29c-60eeadc8f7c1","ownedRelatedElement":[{"id":"9390334a-f844-4352-91a5-f0fbcfa072f7","eClass":"sysml:StateUsage","data":{"declaredName":"heating","elementId":"502e583f-266e-4e03-82d5-9198951b9736","isComposite":true}}]}},{"id":"4486dadb-f285-43a9-b554-b5dbe1f30ec4","eClass":"sysml:FeatureMembership","data":{"elementId":"a87c855f-cbc1-441a-90f9-59427af39f5c","ownedRelatedElement":[{"id":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd","eClass":"sysml:StateUsage","data":{"declaredName":"cooling","elementId":"336fbd96-f982-4f5f-ba7b-611ca08daa02","isComposite":true}}]}},{"id":"b7c0db78-1dfc-4f68-aa58-72a367032fca","eClass":"sysml:FeatureMembership","data":{"elementId":"5027456b-92a5-468a-8dc3-4da4d77356e5","ownedRelatedElement":[{"id":"8e205929-279c-421f-b739-c4d498c114da","eClass":"sysml:AttributeUsage","data":{"declaredName":"currentTemp","elementId":"5e7f955d-d275-4a9f-a4f6-fd91e00c903a","ownedRelationship":[{"id":"5be10aa2-0fcf-4b76-81bc-c700d3889d97","eClass":"sysml:FeatureValue","data":{"elementId":"f590f069-37c2-4b72-b412-0c004e7b3969","ownedRelatedElement":[{"id":"d0dec34a-5aca-420e-b7d6-4530d7ca54b2","eClass":"sysml:LiteralRational","data":{"elementId":"22502ad2-6755-4a78-b001-ae7d823d7a1a","value":20.0}}],"isInitial":true}},{"id":"7f7aafa0-3fc2-4cb5-9aa0-81039d5d4a51","eClass":"sysml:FeatureTyping","data":{"elementId":"fdb43bab-e1cc-4c65-966d-8242a09d6c52","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"8e205929-279c-421f-b739-c4d498c114da"}}],"isComposite":true}}]}},{"id":"a6e0b47d-eb19-4328-b6d6-99e68bfed356","eClass":"sysml:FeatureMembership","data":{"elementId":"9fc5a32e-ece4-4122-bed7-51fc54c19ba1","ownedRelatedElement":[{"id":"541bd9c9-44fa-4440-bebc-3f84820674e8","eClass":"sysml:AttributeUsage","data":{"declaredName":"targetTemp","elementId":"2a8602b9-d12d-40a2-9ca4-eeb421a9e2ed","ownedRelationship":[{"id":"e375b8ff-ef56-407b-8538-52a31352d147","eClass":"sysml:FeatureValue","data":{"elementId":"b63a0860-3159-44cc-922e-e4e962e48d91","ownedRelatedElement":[{"id":"2c01bf77-f6e4-4677-92c3-945189119f2e","eClass":"sysml:LiteralRational","data":{"elementId":"1d6f8b13-f67a-4508-9514-0fdd42ce7a11","value":22.0}}]}},{"id":"de665ea7-84c3-4e42-9a77-f593fe17b134","eClass":"sysml:FeatureTyping","data":{"elementId":"46004252-bb31-4407-9d4d-1e02857d777e","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}],"isComposite":true}}]}},{"id":"8d07b2dd-cb18-4fc0-baa8-f651b807b46c","eClass":"sysml:FeatureMembership","data":{"elementId":"485d35c7-55b7-4e7c-807b-0c65402c854c","ownedRelatedElement":[{"id":"9e405dc0-36d0-47f8-8b8d-461ab5a31169","eClass":"sysml:AttributeUsage","data":{"declaredName":"tolerance","elementId":"c79fd2f6-b87e-45ab-a978-d6e365d1892b","ownedRelationship":[{"id":"30f1fde2-4f4b-4257-8a9d-851f11cc8e6f","eClass":"sysml:FeatureValue","data":{"elementId":"e8a2a7c8-3eb0-4eca-af46-8812cde65a6a","ownedRelatedElement":[{"id":"ae8ef32c-b7d9-4f25-992d-8abc484db859","eClass":"sysml:LiteralRational","data":{"elementId":"ea074070-969d-4a48-b05b-afed056dab84","value":1.0}}]}},{"id":"d4ff4acb-0756-4348-8f5a-ff6f5a4fed41","eClass":"sysml:FeatureTyping","data":{"elementId":"50c766d5-c266-474b-9c43-d2cc1c0c498d","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"9e405dc0-36d0-47f8-8b8d-461ab5a31169"}}],"isComposite":true}}]}},{"id":"7656692f-d1a8-4b63-9969-0191adc8273e","eClass":"sysml:FeatureMembership","data":{"elementId":"d8e1cc5d-5bfb-4195-91db-318eeb0b2706","ownedRelatedElement":[{"id":"0b517687-ef3f-4057-9ce5-27e27f627a22","eClass":"sysml:TransitionUsage","data":{"declaredName":"to_heating","elementId":"722d9bb6-f15a-4133-9baa-5d87384af8b2","ownedRelationship":[{"id":"ad20395d-9921-44c2-8311-8afdcdf04157","eClass":"sysml:Membership","data":{"elementId":"1d757d16-ec70-4b47-a753-7dd9402e02bc","memberElement":"630f2641-b66a-4f52-91c6-057b1c5811d0"}},{"id":"adcd33cb-6cb5-4b17-9c69-ad80369f135b","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"bd902655-656e-4d4f-ac6d-99ba34d0137a","ownedRelatedElement":[{"id":"c0d13f10-13cf-410a-93b7-69d1b4f4c087","eClass":"sysml:OperatorExpression","data":{"elementId":"909fc54a-ec14-443d-a7e9-1a9258b27d6d","ownedRelationship":[{"id":"e2e339c8-0f79-44c9-81cf-688da9cc86da","eClass":"sysml:ParameterMembership","data":{"elementId":"d91c3529-d8b8-43b0-a14b-232d2654054f","ownedRelatedElement":[{"id":"8f6d10d3-a15a-4834-a413-9081216bebce","eClass":"sysml:Feature","data":{"elementId":"3320621a-f1fc-4247-a403-a37ed55995b8","ownedRelationship":[{"id":"e1c4bd58-db2f-4848-87bf-fb137774e651","eClass":"sysml:FeatureValue","data":{"elementId":"1a3215c4-89a3-44af-b565-35507207997d","ownedRelatedElement":[{"id":"332f091f-0037-412f-8e8c-e9a304e1b10b","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"fdcc2e28-f97a-406e-83ab-d125e81e692d","ownedRelationship":[{"id":"e7276e34-09c6-4c65-86c7-697421caa946","eClass":"sysml:Membership","data":{"elementId":"e37224b5-82fd-45ec-9ba8-34c6fd9b69d4","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"cf645d64-56de-4213-90a2-9c4a6db8e579","eClass":"sysml:ParameterMembership","data":{"elementId":"63442128-6cfa-4e4a-ba44-3ce24316184c","ownedRelatedElement":[{"id":"b49feb80-5af2-4e5a-8ba5-dd65c5fa001d","eClass":"sysml:Feature","data":{"elementId":"3ec5ffa8-ecbc-4770-8842-43e4c6fd4d05","ownedRelationship":[{"id":"23ea0751-f45b-40c9-a30f-b147a0208019","eClass":"sysml:FeatureValue","data":{"elementId":"5c869a08-bebb-4042-9604-f5b376c7917a","ownedRelatedElement":[{"id":"402f380f-d296-4ad0-b9ae-43b308744a29","eClass":"sysml:OperatorExpression","data":{"elementId":"239f31d9-f8c8-4ac1-8d16-ecfb64248922","ownedRelationship":[{"id":"381565fe-0971-40f9-961f-316dfa6ee739","eClass":"sysml:ParameterMembership","data":{"elementId":"a3f78dbb-87b2-4ee1-8b89-0ee00d06f7d9","ownedRelatedElement":[{"id":"7b1c47ea-588d-4e27-95bd-f176c085c045","eClass":"sysml:Feature","data":{"elementId":"ee708e17-b539-4407-9c46-d132f00bb033","ownedRelationship":[{"id":"1ed2f67c-7788-40bd-9720-a2303cdf6fb4","eClass":"sysml:FeatureValue","data":{"elementId":"71456a75-6736-4cd9-86ca-f77f486fa746","ownedRelatedElement":[{"id":"8d70366b-37c0-455f-8e68-f598d82f77de","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"a39ef57d-5d4b-4e49-8c21-a81da65fac02","ownedRelationship":[{"id":"3bf0be2e-137b-4b79-820d-b78751628033","eClass":"sysml:Membership","data":{"elementId":"82a0c8ec-b7b1-4b64-9ca2-ff0ab64a1c93","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}},{"id":"3f51c431-426e-4fe0-8a8f-17ba1ac341fb","eClass":"sysml:ParameterMembership","data":{"elementId":"07ce41f0-2342-4371-b8ba-d5db86f2260b","ownedRelatedElement":[{"id":"fe0a71f5-757e-4197-8b98-abccdd56c125","eClass":"sysml:Feature","data":{"elementId":"c90febc4-f41d-4181-a166-47beec2aa460","ownedRelationship":[{"id":"54397d0d-b73d-4062-8384-852d5dd6c98c","eClass":"sysml:FeatureValue","data":{"elementId":"93c019ad-a7ea-42be-904d-ec1acb7d237e","ownedRelatedElement":[{"id":"56513cbf-c7da-496a-8980-edd49dd33bda","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"f3b3bb11-8087-4d66-8d58-dc3ea543897f","ownedRelationship":[{"id":"2040e3cd-2cbd-494b-a2a8-4c562f415347","eClass":"sysml:Membership","data":{"elementId":"a5c43209-6b39-40a0-ba6d-ed8298ac10cd","memberElement":"9e405dc0-36d0-47f8-8b8d-461ab5a31169"}}]}}]}}],"direction":"in"}}]}}],"operator":"-"}}]}}],"direction":"in"}}]}}],"operator":"<"}}],"kind":"guard"}},{"id":"e361c51a-2480-42e1-a181-ce7d079b2e93","eClass":"sysml:OwningMembership","data":{"elementId":"c2b19814-61f6-4e6e-938f-9cf8dd68ef62","ownedRelatedElement":[{"id":"8085cacc-ccab-4176-91bc-f90d138bf7f3","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"25f126b9-bc1f-43b5-8f65-6c11f41c569b","ownedRelationship":[{"id":"bc9dc7b9-9b80-4c4d-80e8-b137d62abf73","eClass":"sysml:EndFeatureMembership","data":{"elementId":"99db0664-a0b4-4ea0-87eb-cb801838d5fe","ownedRelatedElement":[{"id":"93e43e08-43e2-4c01-b101-436fefc0feb7","eClass":"sysml:ReferenceUsage","data":{"elementId":"430bfb97-e843-4c1d-9351-ed828370dcbc","isEnd":true}}]}},{"id":"45680a1a-a4e5-4f8b-933a-2f87141422ce","eClass":"sysml:EndFeatureMembership","data":{"elementId":"cdb2a753-f470-47a3-b073-f980d304fb23","ownedRelatedElement":[{"id":"7fd10dad-a085-472c-b06d-3173f81373b0","eClass":"sysml:ReferenceUsage","data":{"elementId":"28801261-d808-4b8b-a9c4-849aa076620f","ownedRelationship":[{"id":"ca8fd8cd-1fd0-4936-a7e8-474780da6295","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"6bf78264-9a29-4a7d-9f58-af4519b5a245","subsettingFeature":"7fd10dad-a085-472c-b06d-3173f81373b0","referencedFeature":"9390334a-f844-4352-91a5-f0fbcfa072f7"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"50ce6fd3-4386-43e7-9c79-92791f484058","eClass":"sysml:ParameterMembership","data":{"elementId":"4b1fa532-9975-475f-b7a3-2b8dccde5efa","ownedRelatedElement":[{"id":"a50dc602-495e-4cbf-8587-a7909d1e064d","eClass":"sysml:ReferenceUsage","data":{"elementId":"918f482a-795f-4158-9f1b-16f94c2cfb4a","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"211a29e1-2104-4473-bc7a-e7675162e447","eClass":"sysml:FeatureMembership","data":{"elementId":"30842099-ac84-4baf-aae8-d78c11ba491a","ownedRelatedElement":[{"id":"e1c27d0b-476e-42d4-9b81-b5f064d9cbbe","eClass":"sysml:TransitionUsage","data":{"declaredName":"to_cooling","elementId":"3df50466-18d3-48d1-9b1a-6b35ab79f2b7","ownedRelationship":[{"id":"6971555b-4116-48f0-9847-9292f1357d54","eClass":"sysml:Membership","data":{"elementId":"1ae63504-5879-44d8-845c-58145c66cee8","memberElement":"630f2641-b66a-4f52-91c6-057b1c5811d0"}},{"id":"2f3331f5-bbe1-44c4-844b-d24c8f2eeffb","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"f0e1ee9a-8235-4875-b5e3-1ff7f8ac8a85","ownedRelatedElement":[{"id":"ec67ead5-7739-4dd3-a82e-f1bb5ef34268","eClass":"sysml:OperatorExpression","data":{"elementId":"974ce809-d343-4a2f-8fe5-cec41eb46ba4","ownedRelationship":[{"id":"371effd8-5eea-4802-94e5-704498a68b13","eClass":"sysml:ParameterMembership","data":{"elementId":"bc3ab140-50b6-4c33-9874-23ebc399610c","ownedRelatedElement":[{"id":"40353cdf-d10b-4322-b623-05972ba837e3","eClass":"sysml:Feature","data":{"elementId":"664143da-4921-42a1-9cfd-cfc893719859","ownedRelationship":[{"id":"1eea43cc-f48e-4dc3-bf5d-574dd7fadcb9","eClass":"sysml:FeatureValue","data":{"elementId":"4f6f4e36-88e9-4ce7-b53f-2bb46878a9f3","ownedRelatedElement":[{"id":"1440ba96-39f9-4745-9596-625baab83480","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"a06418d2-453e-4ea7-90c6-cedb31a54a93","ownedRelationship":[{"id":"3af419a1-d8cd-4f4e-a95f-03d88df310c5","eClass":"sysml:Membership","data":{"elementId":"94b074ff-c911-4b46-838c-d617bc424d2d","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"b6bbf397-915c-4df2-8153-046eddf48b60","eClass":"sysml:ParameterMembership","data":{"elementId":"1c049222-6ff6-4835-a00a-8df9349d8266","ownedRelatedElement":[{"id":"e73a1795-d083-4539-953e-6ce302c9c7a0","eClass":"sysml:Feature","data":{"elementId":"4b579ae4-8c79-4c88-9b21-db059d7857b7","ownedRelationship":[{"id":"74a4b0ca-269e-480b-b209-5a36bcfcad18","eClass":"sysml:FeatureValue","data":{"elementId":"5a8e236c-908c-478f-94a4-1dccce775e9f","ownedRelatedElement":[{"id":"c656679c-b3f8-4218-8b7c-94f40c432e9e","eClass":"sysml:OperatorExpression","data":{"elementId":"e7eac6ca-3967-41af-8f50-de765b9e7c87","ownedRelationship":[{"id":"90b4fda8-1e61-4157-966d-60ebaa3cecaa","eClass":"sysml:ParameterMembership","data":{"elementId":"8dfcdc00-48ae-4f73-b096-74263b2ff799","ownedRelatedElement":[{"id":"c612b8d5-4885-4c2e-85ed-6d0ad2074202","eClass":"sysml:Feature","data":{"elementId":"c1768702-c8ce-41c2-8c51-8195d64c97b6","ownedRelationship":[{"id":"03915a4e-b0da-48e8-863f-30f53ac37cea","eClass":"sysml:FeatureValue","data":{"elementId":"b00bb56f-0b71-407c-baa4-90956eb99b76","ownedRelatedElement":[{"id":"13070906-e608-4e8d-8418-3fc3916128f0","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"882ab32c-e241-4989-955c-608a9acbae32","ownedRelationship":[{"id":"9726f328-2238-44c6-b640-29ebad59d238","eClass":"sysml:Membership","data":{"elementId":"bc37097c-d761-4b2d-b506-9c807f25c907","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}},{"id":"3d67e9aa-3fc0-4e48-a7a0-632f6b5730c1","eClass":"sysml:ParameterMembership","data":{"elementId":"a56ba801-d9c5-4302-99ae-d5e68376378c","ownedRelatedElement":[{"id":"870fc619-a861-4d71-8b0d-4c700c8c4b3f","eClass":"sysml:Feature","data":{"elementId":"bd432a49-148b-4805-b314-6aaa2b485eba","ownedRelationship":[{"id":"db0aabd1-5712-4faa-86b7-4bd4176b4389","eClass":"sysml:FeatureValue","data":{"elementId":"9702fb41-ed29-4393-bbba-8c6b864eb4e0","ownedRelatedElement":[{"id":"edc353c4-b66d-4b2b-b8d5-55f8246922ab","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"82a521eb-14f5-4e56-be04-49bb2a83678d","ownedRelationship":[{"id":"7e2b0f6f-6c10-4670-aa85-2294aadb7be3","eClass":"sysml:Membership","data":{"elementId":"225dfdb5-3b07-4afd-bb2d-554318c82ed5","memberElement":"9e405dc0-36d0-47f8-8b8d-461ab5a31169"}}]}}]}}],"direction":"in"}}]}}],"operator":"+"}}]}}],"direction":"in"}}]}}],"operator":">"}}],"kind":"guard"}},{"id":"f2dd1298-dec2-44c6-bccc-c6aff0942073","eClass":"sysml:OwningMembership","data":{"elementId":"c405c6cb-696d-4a3f-99e7-6dab852ae228","ownedRelatedElement":[{"id":"c4e5cb98-07df-49a6-a3b1-93e9d9d6f4f5","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"acd50047-bcc8-421f-b204-cef2c540355e","ownedRelationship":[{"id":"73144371-94ed-44bb-95ab-70a1a23360fe","eClass":"sysml:EndFeatureMembership","data":{"elementId":"697afe9a-c1f3-4c65-a063-7bc9ab4b106d","ownedRelatedElement":[{"id":"220c6106-c36f-4497-88e2-42125a9f69d5","eClass":"sysml:ReferenceUsage","data":{"elementId":"b1438ef2-513a-43b5-a292-7e34cd24f941","isEnd":true}}]}},{"id":"39c31f59-67df-408c-bf92-9b1c9dc209df","eClass":"sysml:EndFeatureMembership","data":{"elementId":"7e270dc1-76ee-4023-9d55-128523dd8d26","ownedRelatedElement":[{"id":"9dd8948f-9a7c-4682-bc46-dda6eaf7eed8","eClass":"sysml:ReferenceUsage","data":{"elementId":"8a705bce-88f0-4558-b010-cac84b264413","ownedRelationship":[{"id":"16928b68-0b7c-4da8-891f-bf6fc174361a","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"36718153-4eb3-48ca-8023-b1ca8a606897","subsettingFeature":"9dd8948f-9a7c-4682-bc46-dda6eaf7eed8","referencedFeature":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"6b679136-5121-49fc-b63f-edea84f72f73","eClass":"sysml:ParameterMembership","data":{"elementId":"9d7e2288-1a5a-4ad9-aa04-96f72ddca831","ownedRelatedElement":[{"id":"5d11e636-89f5-4d42-a233-207b6d62d418","eClass":"sysml:ReferenceUsage","data":{"elementId":"8ffbe3d2-f907-4fd2-b2b3-c67ac8ef75bd","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"da3ff9dc-93bb-406a-a2cb-6bb17b551a62","eClass":"sysml:FeatureMembership","data":{"elementId":"6cf8e042-d8f9-41b6-9a1d-3232943b2b14","ownedRelatedElement":[{"id":"c7efc3c8-830f-41f4-a9cb-a3667f7c7637","eClass":"sysml:TransitionUsage","data":{"declaredName":"heating_done","elementId":"6bb2e424-424c-44d4-afb6-3923e8202303","ownedRelationship":[{"id":"c2f144d8-86b6-4dd7-b2ff-7280703d9e5d","eClass":"sysml:Membership","data":{"elementId":"551669f0-c179-4998-8de3-84a03f2255b4","memberElement":"9390334a-f844-4352-91a5-f0fbcfa072f7"}},{"id":"6dac8578-e793-4cc2-9581-59c2ef40532c","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"cf32b8b1-18ec-4787-9eb0-95da2eeb675a","ownedRelatedElement":[{"id":"e9f31b7a-9673-4037-859b-7d6e5775db53","eClass":"sysml:OperatorExpression","data":{"elementId":"514158d0-9ec0-4ca8-8cf6-c201eded035b","ownedRelationship":[{"id":"2b0b4608-771a-4b49-8264-ee9022d5f533","eClass":"sysml:ParameterMembership","data":{"elementId":"c32a9d2f-ed2f-442c-9eef-7f282e73f828","ownedRelatedElement":[{"id":"f9b860f0-3ab9-4b35-a5af-7b87c85aa51a","eClass":"sysml:Feature","data":{"elementId":"be79d529-4b62-4620-96f6-151347ef888a","ownedRelationship":[{"id":"06a57d10-f450-4edc-8d6d-7e9c085d5678","eClass":"sysml:FeatureValue","data":{"elementId":"b8b2fe56-0ab6-41c9-ab2a-fc9f238d4c36","ownedRelatedElement":[{"id":"07ecaa6c-9469-4602-9938-ef4fe35c8e61","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"498a0218-a6a1-4d1d-951d-b9f2fb76a93a","ownedRelationship":[{"id":"2a962769-9796-46c5-a084-e78784f6e775","eClass":"sysml:Membership","data":{"elementId":"4cf777d6-945d-407c-a1ed-e0b1af63fe54","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"925a2b9f-4c32-49a1-9b83-23b44f262ae8","eClass":"sysml:ParameterMembership","data":{"elementId":"2b1b4a8e-8d3e-4611-9e2b-e67fb634a03c","ownedRelatedElement":[{"id":"2a0e96be-a356-424d-a497-1fb6e0a67a75","eClass":"sysml:Feature","data":{"elementId":"b118b738-974f-47c8-9000-e676ff11acf9","ownedRelationship":[{"id":"77fa7bc6-7751-48fd-b4db-811e8ddb0107","eClass":"sysml:FeatureValue","data":{"elementId":"0faa3816-569c-44c2-91f4-0a62629bdc35","ownedRelatedElement":[{"id":"8deba717-e9e8-4359-a7ee-0392cc60da28","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4f0cbbb1-ed40-47c5-9fdc-716954416eca","ownedRelationship":[{"id":"31c29b60-785d-4c12-91ff-1a6bd5cd0a97","eClass":"sysml:Membership","data":{"elementId":"cfb554e6-b753-40aa-8212-646ac2307d97","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}}],"operator":">="}}],"kind":"guard"}},{"id":"52bd3814-e962-4bf3-bdbc-af103344c0ad","eClass":"sysml:OwningMembership","data":{"elementId":"68dca418-736b-429d-b442-271730f62bed","ownedRelatedElement":[{"id":"bf42847e-36cd-4d3d-aa5f-adbda8deedf1","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"1235177c-931e-444e-841a-74a0033b7573","ownedRelationship":[{"id":"71fc2ef3-58ee-46f5-9f59-16782d9d18ca","eClass":"sysml:EndFeatureMembership","data":{"elementId":"64387b5f-6f0c-43c6-8630-9f507376e5e3","ownedRelatedElement":[{"id":"445af89b-6f69-4a1b-bb66-ee2fad4012bd","eClass":"sysml:ReferenceUsage","data":{"elementId":"39473346-c45b-4bf0-a667-771e453ca497","isEnd":true}}]}},{"id":"853b2327-fd95-4281-92d3-39675c9832ff","eClass":"sysml:EndFeatureMembership","data":{"elementId":"ae636aba-2171-48b4-9bc9-36b8e319a679","ownedRelatedElement":[{"id":"b2b75688-a923-4a1f-966d-bacdff99b033","eClass":"sysml:ReferenceUsage","data":{"elementId":"a4debe8e-e4c5-4e03-ac70-94f40d27f9e9","ownedRelationship":[{"id":"43ce1363-6e62-4981-b36e-b8e0b32431f3","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"66ec302b-b8c2-4029-8536-830eeb9904ae","subsettingFeature":"b2b75688-a923-4a1f-966d-bacdff99b033","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"a4f9b12e-4854-450c-a5b4-c13417654040","eClass":"sysml:ParameterMembership","data":{"elementId":"46d97c31-de66-482e-91da-e7fbc6555f7a","ownedRelatedElement":[{"id":"f7e4f511-9110-424d-9787-c4bec859f3bb","eClass":"sysml:ReferenceUsage","data":{"elementId":"e1cdc0e3-a709-4173-9d58-7500c52b4d9f","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"fd55211f-bc7f-4598-8bc1-0a3d4b54f974","eClass":"sysml:FeatureMembership","data":{"elementId":"888f6364-e8aa-4312-8477-baa01db1b493","ownedRelatedElement":[{"id":"8a153941-bf0a-4010-a51e-62acb8bd63bb","eClass":"sysml:TransitionUsage","data":{"declaredName":"cooling_done","elementId":"9bb3b3d0-59ae-43ea-aeeb-27cd95233987","ownedRelationship":[{"id":"5a798e86-8ac9-428c-bd43-983a008a96ce","eClass":"sysml:Membership","data":{"elementId":"150daea0-ca87-4737-b1cc-be68c0708d45","memberElement":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd"}},{"id":"9a4869bf-59f1-40fe-bb41-5b80125eec95","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"0ee132d8-b870-40a6-93b2-0e386ca698ec","ownedRelatedElement":[{"id":"506f2589-c9aa-497d-b9e2-9f3568a1b60e","eClass":"sysml:OperatorExpression","data":{"elementId":"b17dcb88-0404-4a2d-b175-29b5c2430b10","ownedRelationship":[{"id":"9439080c-7bc5-442c-a234-4fbced1722fd","eClass":"sysml:ParameterMembership","data":{"elementId":"03eeff23-1ce5-40e9-b8f8-8c971d8fea9b","ownedRelatedElement":[{"id":"4bb65cfe-8311-4ac1-85d8-1b19421553b0","eClass":"sysml:Feature","data":{"elementId":"12652e9b-2669-4e27-90fb-3d6c3f3a665b","ownedRelationship":[{"id":"6ec15f89-da66-4dc9-bdf1-34a8235a0e60","eClass":"sysml:FeatureValue","data":{"elementId":"516566a3-89e8-4057-8bb4-3238a772efae","ownedRelatedElement":[{"id":"131bcb2c-6bd2-4e48-a392-4bc83d15ec5d","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"71069a61-0947-49ae-82a6-131855801506","ownedRelationship":[{"id":"3b4c7e1b-00ad-4ef4-8f12-87c642d7e340","eClass":"sysml:Membership","data":{"elementId":"b7da76e8-90dd-4816-a096-3bc4d74fcfff","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"4c107a4c-9209-412b-953e-60b1c643382a","eClass":"sysml:ParameterMembership","data":{"elementId":"4e92e729-b2d1-424c-9471-8f8c17cdc6b7","ownedRelatedElement":[{"id":"010203af-dce4-454e-a19a-888ae9c3b675","eClass":"sysml:Feature","data":{"elementId":"401748ba-f2fe-4fd0-903a-bbbfb3067510","ownedRelationship":[{"id":"4ba22430-f1f1-4462-a196-ed8b6e119841","eClass":"sysml:FeatureValue","data":{"elementId":"9854172d-ee15-4e79-9acd-9717b3b5c598","ownedRelatedElement":[{"id":"61a15a33-8067-4d16-a44f-73bf1eb99e2d","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"972b0f23-2c30-42c6-93d4-71b2d291460e","ownedRelationship":[{"id":"364f5f78-67b1-4631-9d0e-01641d95afc9","eClass":"sysml:Membership","data":{"elementId":"cfba9064-3b74-4bf4-bdbf-97e54c8b2013","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}}],"operator":"<="}}],"kind":"guard"}},{"id":"0f19e6b9-2973-411c-b800-8d0ed49795be","eClass":"sysml:OwningMembership","data":{"elementId":"d2755907-2b2e-452f-8051-637f99928b24","ownedRelatedElement":[{"id":"d8aee92a-f512-4762-b4e4-b948f450a024","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"c1cb5168-b133-4e08-8f9f-3243ee80134d","ownedRelationship":[{"id":"9b1ee916-7707-43a1-937c-7cad3d9b5b77","eClass":"sysml:EndFeatureMembership","data":{"elementId":"1526df00-9a9b-41e4-8224-e54e782c429d","ownedRelatedElement":[{"id":"03e69081-de75-4755-8a05-056340bfcf21","eClass":"sysml:ReferenceUsage","data":{"elementId":"b907c9b6-3433-4113-9ed8-34644ca93a8c","isEnd":true}}]}},{"id":"f8423145-7a38-4e0b-848d-67a70db029c6","eClass":"sysml:EndFeatureMembership","data":{"elementId":"2595cd38-81ee-46c6-b87c-7c948a5ab166","ownedRelatedElement":[{"id":"98dfa1ca-9866-4079-b43d-b61af3c53e64","eClass":"sysml:ReferenceUsage","data":{"elementId":"ada1671c-beb1-4333-b144-1c9568840b05","ownedRelationship":[{"id":"629647f9-2a93-493e-883d-d5c0cb6d9fdd","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"de396f89-7470-469c-9ab6-a726f8de8400","subsettingFeature":"98dfa1ca-9866-4079-b43d-b61af3c53e64","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"5ed10d2c-ac2b-4864-9b4f-74218a8119d7","eClass":"sysml:ParameterMembership","data":{"elementId":"8444ae28-737f-4667-b584-a5ec3afd4cc5","ownedRelatedElement":[{"id":"3414baf1-cc30-4843-90e6-ed004d4b11f4","eClass":"sysml:ReferenceUsage","data":{"elementId":"a9f3e3d7-8086-467c-8a9f-040ae5ec8f4a","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}}]}}]}},{"id":"f1ac0d22-7a0f-413b-b576-85a3ffbe6135","eClass":"sysml:OwningMembership","data":{"elementId":"e648c25f-e278-4e65-9133-0dc96e1f0026","ownedRelatedElement":[{"id":"69d595d7-6a07-4cb1-a4ea-e6102b4ec12d","eClass":"sysml:ConcernDefinition","data":{"declaredName":"SafetyAndReliability","elementId":"3c2ae026-8af6-4bf4-bc7c-79234a98eff9","ownedRelationship":[{"id":"ef1499c9-c7f7-4acb-acf5-e8877c9383c8","eClass":"sysml:FeatureMembership","data":{"elementId":"c610ab68-ac78-4599-b05e-7174225eeaa7","ownedRelatedElement":[{"id":"e2678e9c-3155-4570-bd56-4c8457084f05","eClass":"sysml:AttributeUsage","data":{"declaredName":"deploymentCount","elementId":"9c8fd285-2a30-4ee8-9e2b-cc5a38f03e85","ownedRelationship":[{"id":"3e8dbff8-89e0-4113-a368-9080e6e59b45","eClass":"sysml:FeatureValue","data":{"elementId":"7359a844-4139-4401-b296-a9ab08f92acf","ownedRelatedElement":[{"id":"2db9e19e-7b70-420f-bbab-875dd36ee56f","eClass":"sysml:LiteralInteger","data":{"elementId":"05d4dfe9-b7c6-4b85-864b-83f347eee7be","value":3}}]}},{"id":"21d2afe7-e7b0-4994-9dca-09221ba31bf1","eClass":"sysml:FeatureTyping","data":{"elementId":"c6132f83-494c-4a60-bbac-1862a5261fc7","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"e2678e9c-3155-4570-bd56-4c8457084f05"}}],"isComposite":true}}]}},{"id":"5878dce7-7b5a-4f3f-9780-b01ccdd0c379","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"d788cb4d-7166-4e73-ac86-425afa925dec","ownedRelatedElement":[{"id":"5e36a9cd-89d3-4653-b767-0e1be2d32ad5","eClass":"sysml:ConstraintUsage","data":{"elementId":"585f8cab-50a5-47a5-8ea1-3f5929be4af2","ownedRelationship":[{"id":"821531fa-1c3b-468e-aeba-5f2f8ce6e2a4","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"a5488ef2-0227-4422-ac46-dda945fcbf4d","ownedRelatedElement":[{"id":"8a6c830c-98af-403f-a4de-938a31f61194","eClass":"sysml:OperatorExpression","data":{"elementId":"8f0efd41-c032-4a95-b4da-80641f15fa5a","ownedRelationship":[{"id":"298ac857-1424-421a-8895-f8b2ef5cfc55","eClass":"sysml:ParameterMembership","data":{"elementId":"337a51c2-5cb0-4c94-9309-06d838bdb875","ownedRelatedElement":[{"id":"b0ce01ae-8dd1-406b-b61e-6b5c0200a4bc","eClass":"sysml:Feature","data":{"elementId":"bed903ba-e17d-426e-bef1-3c83fed8ad5b","ownedRelationship":[{"id":"1489f1a6-db01-4f94-b7ba-3c221451fbbe","eClass":"sysml:FeatureValue","data":{"elementId":"294d19aa-e1a2-429a-a91e-35b068b48631","ownedRelatedElement":[{"id":"9e0eed6b-d20e-449a-b674-3e54e3d53859","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4affe832-9f21-4775-abf7-9e33ea8c6c8e","ownedRelationship":[{"id":"37daf8ad-f0b9-4ac1-96f1-29da588d1fe5","eClass":"sysml:Membership","data":{"elementId":"bf9614cb-198c-4f53-9f63-0f1aa8820c10","memberElement":"e2678e9c-3155-4570-bd56-4c8457084f05"}}]}}]}}],"direction":"in"}}]}},{"id":"f35b3dda-8d34-4dc3-94e0-e5f7a7accff9","eClass":"sysml:ParameterMembership","data":{"elementId":"2bd75866-58d5-4522-aca1-6cf4196ed16b","ownedRelatedElement":[{"id":"1eace1ad-8813-4660-a1cd-332909552774","eClass":"sysml:Feature","data":{"elementId":"bd79950f-6dbf-4c42-8f2c-06aa4b7744c6","ownedRelationship":[{"id":"64d75861-f3c8-44f3-a0b8-dbf2e7878dc3","eClass":"sysml:FeatureValue","data":{"elementId":"07085d12-61df-40fa-8768-49c55c23e67b","ownedRelatedElement":[{"id":"56c8f7f8-93ef-4666-aa56-53b6531c0d4f","eClass":"sysml:LiteralInteger","data":{"elementId":"1791dfbd-3e30-488c-bbbe-30816bad15bc"}}]}}],"direction":"in"}}]}}],"operator":">"}}]}}],"isComposite":true}}]}},{"id":"597a0e23-3eef-471c-8dbd-75562a4e4d7a","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"b0aef8c1-d38c-4bd9-8ae2-4f0542fe91d7","ownedRelatedElement":[{"id":"b34a95e4-cb32-4a1c-b1ee-17d4bd62c7d2","eClass":"sysml:ConstraintUsage","data":{"declaredName":"minimumRedundancy","elementId":"76a7a9b1-9ecc-42b1-9a41-5b328053f12f","ownedRelationship":[{"id":"8c80e3db-82fa-41c4-be21-274b737f7284","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"dbb57839-6678-448a-8221-be6911b0f848","ownedRelatedElement":[{"id":"ed00c629-0f82-4874-9590-5a775e35081d","eClass":"sysml:OperatorExpression","data":{"elementId":"c67dae08-fad7-409c-ae7b-ee013cca30d6","ownedRelationship":[{"id":"7d801324-bad9-46b1-970f-7a2b38a556aa","eClass":"sysml:ParameterMembership","data":{"elementId":"8a478841-dab9-42a1-8966-ed68ec3be498","ownedRelatedElement":[{"id":"dc503057-d95b-4569-b694-9c03d8a4a711","eClass":"sysml:Feature","data":{"elementId":"5ee82585-9fb8-4395-8b39-e9ffc2ac6d80","ownedRelationship":[{"id":"8c469bc4-c47f-4ea8-9b6d-2aa4c643d7c1","eClass":"sysml:FeatureValue","data":{"elementId":"e1671e98-bc6d-4194-84c8-6f79c29850c0","ownedRelatedElement":[{"id":"2d5735e7-8a41-4fd8-856e-46af848a86f0","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"7f2be62b-42dc-4161-bbf1-9e33a596e6f7","ownedRelationship":[{"id":"cf8e2ed0-00d1-4e87-8a2f-b23d7c6c2879","eClass":"sysml:Membership","data":{"elementId":"f11aecf9-0c21-45a8-843f-fe5d4d96a0a9","memberElement":"e2678e9c-3155-4570-bd56-4c8457084f05"}}]}}]}}],"direction":"in"}}]}},{"id":"6f077a43-6f45-49b1-9232-b3282f0abb57","eClass":"sysml:ParameterMembership","data":{"elementId":"c2c6e7b8-af06-4096-989a-3c2e95baca51","ownedRelatedElement":[{"id":"0309d85e-37cc-499f-b876-846b2d5a4c2a","eClass":"sysml:Feature","data":{"elementId":"ca1bdcc4-dadc-4228-8d61-813b74f39cc7","ownedRelationship":[{"id":"dfad1497-873d-4629-a277-c254e1a247a9","eClass":"sysml:FeatureValue","data":{"elementId":"a50bbd08-8668-4de4-a64f-016da901a339","ownedRelatedElement":[{"id":"d1b9e2c7-f50f-44a3-a585-7f531eb3fbf9","eClass":"sysml:LiteralInteger","data":{"elementId":"48a9725a-a225-454e-8421-a03542e9e7e8","value":2}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"isComposite":true}}],"kind":"requirement"}}]}}]}},{"id":"a6f07c1f-b22d-4081-a3d9-3fc78dee4d22","eClass":"sysml:OwningMembership","data":{"elementId":"db5e69df-ce41-43a4-a9c1-2655173fae74","ownedRelatedElement":[{"id":"da2296a4-25ed-4f04-abc8-d47f93cd223c","eClass":"sysml:ConcernDefinition","data":{"declaredName":"PerformanceConcern","elementId":"719defb0-780c-486b-85d5-b3d4e5b460cc","ownedRelationship":[{"id":"d1836f12-7281-4b5b-a0d2-26cfef749277","eClass":"sysml:SubjectMembership","data":{"elementId":"35bf0d61-c429-43fb-8f17-f6059aa0c4d3","ownedRelatedElement":[{"id":"33466a30-d081-4d0d-a3dc-142c59b82000","eClass":"sysml:ReferenceUsage","data":{"declaredName":"s","elementId":"ea6f2066-3a2f-4888-9eb8-33e6cec61b8d","ownedRelationship":[{"id":"1355d4f4-a4c7-4a0c-bb4a-a8dd29b2c3df","eClass":"sysml:FeatureTyping","data":{"elementId":"caea1502-7778-408f-ac2b-db317a07154f","type":"3f2124ff-5c56-486b-a296-b1c3476e5180","typedFeature":"33466a30-d081-4d0d-a3dc-142c59b82000"}}],"direction":"in","isComposite":true}}]}},{"id":"a4eda0c9-d3e4-4ebc-8d8b-0c864423acf4","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"fbab8f7d-eaf7-4510-bed3-2679d739229a","ownedRelatedElement":[{"id":"4fd2c402-15b7-4546-ad9c-7aa9419a1528","eClass":"sysml:ConstraintUsage","data":{"elementId":"98f1df4b-ff5c-498a-960b-9cb66ef0dbf9","ownedRelationship":[{"id":"36d9f176-7ed6-4905-b29d-6db221ad4a48","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"d31f27bd-7365-447b-8efe-fc63beb6a4cb","ownedRelatedElement":[{"id":"e0b5902b-0568-4ac2-86f8-9c99ee2ea99d","eClass":"sysml:OperatorExpression","data":{"elementId":"1bd5e29a-49b9-445e-8f28-a08c8f3789d2","ownedRelationship":[{"id":"2894d269-7449-43a5-b869-1c8ade17cfd4","eClass":"sysml:ParameterMembership","data":{"elementId":"c4e7842a-2eb7-4166-b2d4-d22629679d2d","ownedRelatedElement":[{"id":"3beee5fd-cf76-4519-8c61-83a455ab8844","eClass":"sysml:Feature","data":{"elementId":"d9bff176-b230-4c4c-acab-e984bf66cb07","ownedRelationship":[{"id":"acf8beeb-646a-428e-8468-7bf544fbca3e","eClass":"sysml:FeatureValue","data":{"elementId":"82fb5d89-009e-4f42-9c2a-a207d72de8cd","ownedRelatedElement":[{"id":"d5eac072-23fc-4597-af6e-4efeb7b922f3","eClass":"sysml:FeatureChainExpression","data":{"elementId":"8631de4f-c2a3-4a5e-abc4-f289fcad9cbf","ownedRelationship":[{"id":"00f7dd36-bc59-4888-98ca-cde32b4d2019","eClass":"sysml:ParameterMembership","data":{"elementId":"d6784867-db24-4ae7-a33a-51e3097ecf79","ownedRelatedElement":[{"id":"c6085eea-d204-47b7-9b9b-afbb857fa5eb","eClass":"sysml:Feature","data":{"elementId":"2305a2c5-7944-43d8-a2f3-7fca0cc8b13d","ownedRelationship":[{"id":"95f831d5-d054-428c-979f-370ab457876b","eClass":"sysml:FeatureValue","data":{"elementId":"db43790f-95ec-43ab-b828-6931bfec969d","ownedRelatedElement":[{"id":"9109e87b-a6be-4945-bb4b-fb5f5eb72182","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"1eeaf8dc-1714-4312-b916-a2f4150c49e3","ownedRelationship":[{"id":"99a0541b-69f4-4e6f-84e1-37726c94e2ef","eClass":"sysml:Membership","data":{"elementId":"e1933442-132c-465f-9089-97a232dbca20","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"e67f2a70-47dd-4bd1-8df8-648804d9119e","eClass":"sysml:Membership","data":{"elementId":"c38669f1-fd86-4202-bb78-2d1aa53a8bb4","memberElement":"edc4f7bc-7d24-498e-8e76-ae1743668254"}}]}}]}}],"direction":"in"}}]}},{"id":"58d3fffa-c939-4a30-ae84-420ce97dba7a","eClass":"sysml:ParameterMembership","data":{"elementId":"c0a65af3-b764-47f5-8419-9d576135cbd1","ownedRelatedElement":[{"id":"91e41df5-a707-4754-adf1-7fb1319dc177","eClass":"sysml:Feature","data":{"elementId":"d89c649d-d83b-47ff-bf51-8e87eca905c6","ownedRelationship":[{"id":"a1e38bd6-5f5b-4551-8180-5901c46888cc","eClass":"sysml:FeatureValue","data":{"elementId":"18009365-ec4c-4f5f-a0c5-9545dad99c38","ownedRelatedElement":[{"id":"e84c5e93-fc46-4cf0-a0bf-f7cd4f7f16ce","eClass":"sysml:LiteralBoolean","data":{"elementId":"44d2e95b-1bef-4415-ac11-f0ff315c5445","value":true}}]}}],"direction":"in"}}]}}],"operator":"=="}}]}}],"isComposite":true}}]}},{"id":"934e8eac-2e71-4b04-b759-d928aee33336","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"df1c9c38-1d8b-49e6-b8f9-4cdc9af5b9d9","ownedRelatedElement":[{"id":"6891b4f5-6f02-4c73-ae23-db88ad10b253","eClass":"sysml:ConstraintUsage","data":{"declaredName":"responsiveness","elementId":"c0f01f9c-e59f-4517-9d2c-a295ce86c4b2","ownedRelationship":[{"id":"d20bfa80-aa30-436f-a5bf-96e2217efa58","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"33ea9c9a-383c-4d7e-b356-6df68a277de9","ownedRelatedElement":[{"id":"6f2e1644-b09d-46a2-b155-fc123e0f2953","eClass":"sysml:OperatorExpression","data":{"elementId":"378814e3-5c6b-4aac-983b-56d7ba918c1d","ownedRelationship":[{"id":"93a8bf8c-3c78-47f4-be7a-5bfe2faccaa3","eClass":"sysml:ParameterMembership","data":{"elementId":"8b7301cd-24b5-4b2b-8e1a-5a0dc096bdbc","ownedRelatedElement":[{"id":"fb7b2c32-7fe5-4ad7-bf3c-fc17280e4f4b","eClass":"sysml:Feature","data":{"elementId":"5a5849ab-2fa4-4966-8981-e252afcbe1f8","ownedRelationship":[{"id":"3a8347bc-70f7-4de8-892f-676542d63765","eClass":"sysml:FeatureValue","data":{"elementId":"dc48009e-02ff-4dd9-8986-71bef33e499f","ownedRelatedElement":[{"id":"501238ee-b170-4a71-add9-c3cc4b62b541","eClass":"sysml:OperatorExpression","data":{"elementId":"b4f2d2fc-f450-48f8-ade1-138bedd954ab","ownedRelationship":[{"id":"0e53a9bd-1bd5-4b12-931c-da6a744381be","eClass":"sysml:ParameterMembership","data":{"elementId":"2eecf130-286c-498a-b073-6ccd04e790dd","ownedRelatedElement":[{"id":"244833c3-2b41-467a-bb18-03bdca1aaf91","eClass":"sysml:Feature","data":{"elementId":"35c7ccb4-753a-4b3b-8bee-1e87f1faba9d","ownedRelationship":[{"id":"c2125fb7-4da1-4c18-ae2d-545b2ca6e3d3","eClass":"sysml:FeatureValue","data":{"elementId":"09b48893-6827-4cf9-bec6-88b807844c19","ownedRelatedElement":[{"id":"c19dca8a-1bed-49cd-a027-c10b6570e483","eClass":"sysml:FeatureChainExpression","data":{"elementId":"7a3c3fe4-404d-4889-9e34-1a3dd5ce5ca5","ownedRelationship":[{"id":"2febd014-6a70-48ac-9a28-211fb0cfc2bb","eClass":"sysml:ParameterMembership","data":{"elementId":"57bc8b4b-0a38-4b7f-b3a6-5d0523cc728c","ownedRelatedElement":[{"id":"a236b40b-3240-4162-8309-ba8de4a00b11","eClass":"sysml:Feature","data":{"elementId":"8a6e54a2-dd2a-46c2-840e-a0444dfc17d7","ownedRelationship":[{"id":"d4999cc0-72f8-418c-8a16-8d362577a450","eClass":"sysml:FeatureValue","data":{"elementId":"1371d3c0-f0db-4df2-b39a-86196bffcd6a","ownedRelatedElement":[{"id":"50e3db21-7e60-491c-ac6c-9a7dc9407207","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4257cf6d-7f15-4fe9-b48e-24a072c6f040","ownedRelationship":[{"id":"87ec1ec4-0515-440b-b35c-8b8581217414","eClass":"sysml:Membership","data":{"elementId":"294b0f69-810d-4be2-bbdc-2022d8aa9794","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"091ee316-159d-400d-94b8-ba0aa5c2f9b5","eClass":"sysml:Membership","data":{"elementId":"1dac782f-da3d-4fe4-9d47-3fa569692bcc","memberElement":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}]}}]}}],"direction":"in"}}]}},{"id":"379e1891-786a-48ee-96a3-d6e3b00cde72","eClass":"sysml:ParameterMembership","data":{"elementId":"ef6e61be-424e-4063-bf2f-a81da5029fcc","ownedRelatedElement":[{"id":"fefc7b1f-cd73-4ef5-95bf-37f12b0749b8","eClass":"sysml:Feature","data":{"elementId":"d080d7d8-b587-4f09-8546-3b7515b73bf7","ownedRelationship":[{"id":"b08c94c0-5fd7-4498-81f8-91cc16df465e","eClass":"sysml:FeatureValue","data":{"elementId":"47f17548-693b-4b52-b6c5-146f93103b88","ownedRelatedElement":[{"id":"f8e0dcc5-6e48-4e37-a14d-37a1026ee01a","eClass":"sysml:LiteralRational","data":{"elementId":"39ac2b8c-4701-4616-8d73-6dc7ffe2c9cd","value":50.0}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"direction":"in"}}]}},{"id":"eb8516c8-e8c8-4ee8-939a-55325c8b1cea","eClass":"sysml:ParameterMembership","data":{"elementId":"218a433e-cfa0-4902-9b4e-f0587be3b80e","ownedRelatedElement":[{"id":"c5b2f829-df1b-40ce-83d3-113b3bbfaba5","eClass":"sysml:Feature","data":{"elementId":"4134c6cb-8c93-4d25-af07-c284f7be3969","ownedRelationship":[{"id":"d60596d0-3c29-41a6-b460-898ed9b4c263","eClass":"sysml:FeatureValue","data":{"elementId":"7d1049c4-86cf-4589-b629-8d63970b8583","ownedRelatedElement":[{"id":"eb62764e-be00-4f53-a943-2bb9afe26d4c","eClass":"sysml:OperatorExpression","data":{"elementId":"00efad22-e113-41bc-be71-47de9a1fb9a8","ownedRelationship":[{"id":"64060226-0dc0-4dc1-8a5e-d01c98830213","eClass":"sysml:ParameterMembership","data":{"elementId":"300b058f-b25b-4281-90fe-684eb92606de","ownedRelatedElement":[{"id":"380808e7-4aa1-4f04-8296-8dbe5d1b9fc1","eClass":"sysml:Feature","data":{"elementId":"63ae1974-7814-4c0a-893e-72850334c386","ownedRelationship":[{"id":"23d8c3ac-ca81-45bb-956a-8e8597b49033","eClass":"sysml:FeatureValue","data":{"elementId":"8a290ed0-03f2-495d-bbc6-28f3570feb4b","ownedRelatedElement":[{"id":"4ad5fcc2-dcbe-4254-8e63-f4dc78552ad9","eClass":"sysml:OperatorExpression","data":{"elementId":"ff15a082-0091-4e71-bdf4-8cd81328f2ca","ownedRelationship":[{"id":"3949740d-1e51-4a76-81d9-66066d200c63","eClass":"sysml:ParameterMembership","data":{"elementId":"c63c1f9d-e626-47dc-9d32-59038df3b448","ownedRelatedElement":[{"id":"9a3ac2bf-cc5f-4854-87bc-14a035ad38e5","eClass":"sysml:Feature","data":{"elementId":"47d4f5d4-feb4-404c-9d39-e36cec21db8e","ownedRelationship":[{"id":"9d85853c-5921-4c83-a954-2d022e66f86d","eClass":"sysml:FeatureValue","data":{"elementId":"3f3a18b5-da04-4aa6-831c-984e8a65d47b","ownedRelatedElement":[{"id":"d3f88bd1-b325-4743-920b-e29c5806d7ef","eClass":"sysml:FeatureChainExpression","data":{"elementId":"f0d776b0-fd96-4282-aecd-722d89b96cff","ownedRelationship":[{"id":"89988082-a6b7-408a-99e5-9601ce0a1bf6","eClass":"sysml:ParameterMembership","data":{"elementId":"6ec39eba-a272-4db0-8c70-d16ea7517f86","ownedRelatedElement":[{"id":"51df5f6b-5cb6-48e7-9677-080c823eacca","eClass":"sysml:Feature","data":{"elementId":"53f44fae-071d-4263-9fde-7dc008d14df0","ownedRelationship":[{"id":"e741aa76-c4bc-4afc-95a6-d9d947a279c6","eClass":"sysml:FeatureValue","data":{"elementId":"a938aad2-2fb1-4258-b1c0-730ab660880b","ownedRelatedElement":[{"id":"ef20405c-9d4d-4ee5-bd10-b353bd9d8e1f","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"0e23e1a9-17f0-4ee1-bd4e-9ca406eece66","ownedRelationship":[{"id":"8938cb64-37ff-421a-82c4-3e1fbc43ddd4","eClass":"sysml:Membership","data":{"elementId":"4b50d9b9-0289-4edc-852e-b9037b2ef60f","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"3045651a-778a-43ae-bdb0-b7072ec4bac1","eClass":"sysml:Membership","data":{"elementId":"1a41f919-9831-4a8b-b7ba-5c628414b769","memberElement":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}]}}]}}],"direction":"in"}}]}},{"id":"fad2ff7a-212e-42e4-9a73-3f8c603d3d37","eClass":"sysml:ParameterMembership","data":{"elementId":"57db7214-0217-449d-8a9b-af78d0334a26","ownedRelatedElement":[{"id":"7c261030-6e18-4072-b4d8-5e700f06f982","eClass":"sysml:Feature","data":{"elementId":"a885a849-350f-41a8-acae-f10b40a21ae8","ownedRelationship":[{"id":"4fc87293-d300-4bdf-b824-c54f9fc9dd91","eClass":"sysml:FeatureValue","data":{"elementId":"1b1e8333-e3e8-4ebc-89b5-1a30a9f54b19","ownedRelatedElement":[{"id":"8d96afc1-c7dd-42ad-a350-57f0b800cc38","eClass":"sysml:LiteralRational","data":{"elementId":"576e66e8-67b6-49c2-957d-738dc65e0309"}}]}}],"direction":"in"}}]}}],"operator":"!="}}]}}],"direction":"in"}}]}},{"id":"03c4fde9-59c7-4499-b22c-f76128218acc","eClass":"sysml:ParameterMembership","data":{"elementId":"8b82cb63-e3d2-410a-86d5-053d9c4de34e","ownedRelatedElement":[{"id":"7949920d-fef9-4ada-a1fd-6146f740a9af","eClass":"sysml:Feature","data":{"elementId":"13999012-8669-458a-9a12-09a4344c25c5","ownedRelationship":[{"id":"7f0c0cbc-d241-42e4-9631-63195ec2387e","eClass":"sysml:FeatureValue","data":{"elementId":"4ae968bd-9835-490f-b122-70579a109558","ownedRelatedElement":[{"id":"4ca5a50e-d116-4b29-9e5c-bff45c6685d9","eClass":"sysml:OperatorExpression","data":{"elementId":"097d302b-bd39-4fdf-b37d-bfaf274d684a","ownedRelationship":[{"id":"c1b9246d-6c33-4efa-8349-63eca55ed258","eClass":"sysml:ParameterMembership","data":{"elementId":"acbda919-a449-4e50-8769-21c05c333f6e","ownedRelatedElement":[{"id":"7b99f3f9-9a46-4dc1-b31b-15b4f243e8e2","eClass":"sysml:Feature","data":{"elementId":"72c64d09-668a-4881-94f2-a02ee97e7f08","ownedRelationship":[{"id":"1ccd4617-8a24-40c1-b1bf-e14c57948d68","eClass":"sysml:FeatureValue","data":{"elementId":"df287639-e735-491a-8fe5-77e377244ea0","ownedRelatedElement":[{"id":"3b7a7f00-42b4-4962-8249-201ea3546292","eClass":"sysml:FeatureChainExpression","data":{"elementId":"39c623a8-db65-483c-b49d-6476f1eb02a7","ownedRelationship":[{"id":"c4b1bdfe-008a-42e2-a0da-560ef61c0657","eClass":"sysml:ParameterMembership","data":{"elementId":"dd1c5acd-02d0-40d5-a509-f934c915227d","ownedRelatedElement":[{"id":"f952d5b2-527e-4487-ad14-a501cbb4ec32","eClass":"sysml:Feature","data":{"elementId":"2302b015-7719-4042-9929-e4ad7cf7b1eb","ownedRelationship":[{"id":"ce4564b8-6fe7-49fc-a146-5d14b3c7405e","eClass":"sysml:FeatureValue","data":{"elementId":"6b6dae15-eda9-4734-8313-71897cfb4fe1","ownedRelatedElement":[{"id":"cbb045fe-e306-4bf8-84ed-e105822603f7","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"dac96cd8-1b64-4b8f-86d2-f9c162cb33a2","ownedRelationship":[{"id":"1fcde9a2-93af-4f46-b5af-0e6b2c94f94e","eClass":"sysml:Membership","data":{"elementId":"ec45938e-93b4-4039-8f0c-8fb5fae4bea0","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"c3ae80a8-eeb0-4fd4-8d1a-36b18bf83520","eClass":"sysml:Membership","data":{"elementId":"b81cd454-88de-46fa-b993-db22a7a5d0bb","memberElement":"4d2f8465-d748-4b68-a5a8-d61c03031bd3"}}]}}]}}],"direction":"in"}}]}},{"id":"11ebb0eb-72cc-46a0-98f6-c135660b2e82","eClass":"sysml:ParameterMembership","data":{"elementId":"db89e0f5-6177-4b68-8850-44f7e32dd602","ownedRelatedElement":[{"id":"479d4b8c-c79b-42d3-805a-afc1dfa21852","eClass":"sysml:Feature","data":{"elementId":"83978f47-55dd-4399-a8b4-e84a7c03c13d","ownedRelationship":[{"id":"20aa93bd-a3fc-4985-b34a-c7d0cb4f8a98","eClass":"sysml:FeatureValue","data":{"elementId":"5ab031d1-3718-46a1-ae8c-c1eb2f226c3d","ownedRelatedElement":[{"id":"0f874cca-dc06-4430-89b8-a00dee51eaee","eClass":"sysml:LiteralInteger","data":{"elementId":"88c30f81-c3ce-4804-9142-c0b33f51dcd3"}}]}}],"direction":"in"}}]}}],"operator":"=="}}]}}],"direction":"in"}}]}}],"operator":"|"}}]}}],"direction":"in"}}]}}],"operator":"&"}}]}}],"isComposite":true}}],"kind":"requirement"}}]}}]}}]}}]}}]}}]}', '2026-04-28 09:22:34.945427+00', '2026-04-28 09:22:34.945427+00', false); +INSERT INTO public.document (id, semantic_data_id, name, content, created_on, last_modified_on, is_read_only) VALUES ('ef3e6929-0415-4295-b42f-64bed8bd4f55', 'aac82b89-8d53-4b16-91b4-deccc180ba62', 'expressions.sysml', '{"json":{"version":"1.0","encoding":"utf-8"},"ns":{"sysml":"http://www.eclipse.org/syson/sysml"},"migration":{"lastMigrationPerformed":"DiagramStyleDescriptionAddMigrationParticipant","migrationVersion":"2026.5.0-202603171430"},"content":[{"id":"152e5a5b-2b71-4653-8b7f-d46df76cd595","eClass":"sysml:Namespace","data":{"eAnnotations":[{"source":"org.eclipse.syson.sysml.imported"}],"elementId":"cfa2873f-f2f4-475a-8817-9f73e2dff74f","ownedRelationship":[{"id":"bea4a5f8-cc39-4cc0-ab5c-226fcf86f737","eClass":"sysml:OwningMembership","data":{"elementId":"eeda408c-b3e7-41af-a52b-3463777d41c0","ownedRelatedElement":[{"id":"baf5ea6a-7861-4b92-8be2-3fe7a2ebc415","eClass":"sysml:Package","data":{"declaredName":"Expressions","elementId":"6ff78b89-10b8-44f5-817f-50ea23e0c620","ownedRelationship":[{"id":"d8072b8b-400f-4968-b1e2-6601ba10bdc7","eClass":"sysml:NamespaceImport","data":{"elementId":"f2a55343-1f9c-4cc6-9912-8ca86dab734e","importedNamespace":"sysml:LibraryPackage kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#40bb440c-5036-58e1-8675-5afccb8b8f1d"}},{"id":"63ed369c-92bd-48cf-ba76-147c1ec13316","eClass":"sysml:OwningMembership","data":{"elementId":"033678d4-289b-46d1-9704-d97a006fb024","ownedRelatedElement":[{"id":"2bde22f7-a834-4afa-84bf-1bae1bb434d8","eClass":"sysml:PartDefinition","data":{"declaredName":"Tank","elementId":"e5e396e4-635f-44a2-8d85-50e19b94a6e7","ownedRelationship":[{"id":"bd7b6c14-0803-423c-b5d9-f368d8c32e6d","eClass":"sysml:FeatureMembership","data":{"elementId":"66064f96-7440-4236-bb21-11bb8c61224c","ownedRelatedElement":[{"id":"15ccc1e3-16b9-4ddf-9959-43141f32d48e","eClass":"sysml:AttributeUsage","data":{"declaredName":"pressure","elementId":"7479570e-234f-4603-a764-d45ba1228aad","ownedRelationship":[{"id":"470e47da-8c4f-45be-a841-5bb4fa82f8da","eClass":"sysml:FeatureTyping","data":{"elementId":"4f77e08f-1a50-4056-a6cb-283b6c0de857","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"15ccc1e3-16b9-4ddf-9959-43141f32d48e"}}],"isComposite":true}}]}},{"id":"27c51649-9b3b-471c-b846-33f10fe82332","eClass":"sysml:FeatureMembership","data":{"elementId":"747b5a9e-95de-4908-a7f0-3917cb4385ae","ownedRelatedElement":[{"id":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a","eClass":"sysml:AttributeUsage","data":{"declaredName":"maxPressure","elementId":"058dca9f-5c49-4ae6-8f71-5e11df5b4021","ownedRelationship":[{"id":"01c173ba-5433-45f6-a9ad-5abf786562c9","eClass":"sysml:FeatureValue","data":{"elementId":"2a6cd6e7-6af0-426b-b6e9-1749f4cae266","ownedRelatedElement":[{"id":"703297e9-e397-496c-ac9a-49b2afff4ba7","eClass":"sysml:LiteralRational","data":{"elementId":"6a768b6c-2898-4dfa-aa7c-2a7f3a9fd6e4","value":600.0}}]}},{"id":"bb766cff-de2c-469f-90b8-06bd35514038","eClass":"sysml:FeatureTyping","data":{"elementId":"9e91a82c-3c8b-43f5-96eb-a92781f5a8d8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a"}}],"isComposite":true}}]}},{"id":"77e243ce-1879-49a5-a4e6-ec8d91b8da9f","eClass":"sysml:FeatureMembership","data":{"elementId":"2a061597-9b75-422f-ac99-17317f4076a9","ownedRelatedElement":[{"id":"7c2ed44f-f991-4559-8594-cfd844160744","eClass":"sysml:AttributeUsage","data":{"declaredName":"volume","elementId":"87f09d7d-87a8-4edf-8c96-eb7d13c44702","ownedRelationship":[{"id":"9789b076-4604-4407-b662-6179ab76b2c5","eClass":"sysml:FeatureValue","data":{"elementId":"7625d338-d5ed-4050-bf6a-a22c75ea21af","ownedRelatedElement":[{"id":"a512cb6b-9395-48b9-88ba-fcb8b2754484","eClass":"sysml:LiteralRational","data":{"elementId":"cfa46233-fa49-4eef-b384-fc4a5861c39a","value":500.0}}]}},{"id":"91584942-a0c5-46f9-bd52-c252b9c0a285","eClass":"sysml:FeatureTyping","data":{"elementId":"cce82e52-823f-4f33-85ac-765af147c2f8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"7c2ed44f-f991-4559-8594-cfd844160744"}}],"isComposite":true}}]}},{"id":"f5d0e91d-5d51-490e-93cf-42662bdb62e8","eClass":"sysml:FeatureMembership","data":{"elementId":"a3c78e1d-535a-4e89-a9cf-d97a00080b81","ownedRelatedElement":[{"id":"e7292249-00ff-41d1-a8b5-783668e88cc0","eClass":"sysml:AttributeUsage","data":{"declaredName":"minVolume","elementId":"6e6f68f1-9144-46ab-8b05-50d964f904a6","ownedRelationship":[{"id":"4c81d9e3-e5c9-4320-9cb1-395c353a73d1","eClass":"sysml:FeatureValue","data":{"elementId":"f861ccab-1624-4cee-ad26-1dfdc733163c","ownedRelatedElement":[{"id":"8e41e070-5926-4d74-9c76-d727d69d5fde","eClass":"sysml:LiteralRational","data":{"elementId":"d9800108-0bfd-4553-bd4a-ef16d51c1b38","value":10.0}}]}},{"id":"fcbae3ff-aeb7-48b2-97a0-55f8aa446d89","eClass":"sysml:FeatureTyping","data":{"elementId":"17d1e180-0632-4bec-9c10-0b166eb462f0","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"e7292249-00ff-41d1-a8b5-783668e88cc0"}}],"isComposite":true}}]}},{"id":"4c5f7f98-0312-4d3b-b2ac-b5a05fdb5e2f","eClass":"sysml:FeatureMembership","data":{"elementId":"b77a0d5e-7cf2-4978-a622-420c88455097","ownedRelatedElement":[{"id":"d9926727-7378-4177-a940-2fb6c1c89dce","eClass":"sysml:AttributeUsage","data":{"declaredName":"maxVolume","elementId":"c957466a-8bd4-448c-b2e5-545af7d9cadc","ownedRelationship":[{"id":"8f9592ef-9513-4025-ab13-e7d7f822f7d8","eClass":"sysml:FeatureValue","data":{"elementId":"5fd01a42-4bde-4a47-8b52-54a7c60049c1","ownedRelatedElement":[{"id":"a9216e54-f44c-4b1f-b262-13650324d325","eClass":"sysml:OperatorExpression","data":{"elementId":"ba3cea85-2725-4b96-a2af-a9159e84a7a9","ownedRelationship":[{"id":"b88c3a9d-0ce2-426e-a333-77225c45d429","eClass":"sysml:ParameterMembership","data":{"elementId":"4b58a948-936f-4567-9cb5-77739aee17c3","ownedRelatedElement":[{"id":"1ae9086c-60a8-4e6b-a24f-db44e021761b","eClass":"sysml:Feature","data":{"elementId":"19bfc3af-4154-4848-bd2e-59a1754b47df","ownedRelationship":[{"id":"52bad1f8-ee55-4bd5-aa2b-db12ec015c26","eClass":"sysml:FeatureValue","data":{"elementId":"0b26ad14-8872-4a9b-ac55-dac0f189df10","ownedRelatedElement":[{"id":"01ee6181-e890-4277-93fb-4bccf84bf3e6","eClass":"sysml:LiteralRational","data":{"elementId":"eb76a535-cb0d-4efd-b0f7-430b46d85d1a","value":100.0}}]}}],"direction":"in"}}]}},{"id":"8ed9cb6c-2fb5-43af-9bcf-9f2b83ea6e1b","eClass":"sysml:ParameterMembership","data":{"elementId":"c1df91fb-cea4-45f0-80a3-191171afb130","ownedRelatedElement":[{"id":"0222cbc2-571d-41ca-9aa6-5b7128062066","eClass":"sysml:Feature","data":{"elementId":"22361eb7-6a20-4f84-853a-cc4373032846","ownedRelationship":[{"id":"b31231a4-f853-4b71-ace4-eaab66065097","eClass":"sysml:FeatureValue","data":{"elementId":"49b00782-9d36-43a2-8a66-04d1e739daba","ownedRelatedElement":[{"id":"772d1b21-03f3-4299-aac5-564d787129b5","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"74181cea-a48b-4dbc-a45b-878f026c065f","ownedRelationship":[{"id":"576e21f5-e5b3-4a54-b6a7-636f4f2b7034","eClass":"sysml:Membership","data":{"elementId":"ef7b0f68-6c53-4d49-9537-eb3a561b1d91","memberElement":"e7292249-00ff-41d1-a8b5-783668e88cc0"}}]}}]}}],"direction":"in"}}]}}],"operator":"*"}}]}},{"id":"5f49fe65-264b-4773-9aa5-48ed839d4a86","eClass":"sysml:FeatureTyping","data":{"elementId":"c9ba2582-5b2d-4339-a4d9-edf1d05a350c","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"d9926727-7378-4177-a940-2fb6c1c89dce"}}],"isComposite":true}}]}},{"id":"bcb92dbe-1c98-4fbc-89bf-6a420f65d587","eClass":"sysml:FeatureMembership","data":{"elementId":"50960f37-4657-4ff4-9b24-01cf5d4839d5","ownedRelatedElement":[{"id":"7d42ee06-3c27-4eaa-9438-344fc789906a","eClass":"sysml:ConstraintUsage","data":{"declaredName":"pressureLimit","elementId":"0349f315-d32d-43e9-9627-9228da3bb552","ownedRelationship":[{"id":"d40b295e-159f-44fe-84a8-fa114dac3472","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"27e134d7-60b2-4a41-a2eb-ed1ca6c1a119","ownedRelatedElement":[{"id":"faa3b115-5b07-4ecf-9147-0d58ceffaf9c","eClass":"sysml:OperatorExpression","data":{"elementId":"d909007a-ddd7-4e31-b17a-4653dfa8cef8","ownedRelationship":[{"id":"94611d95-3c3d-45a8-813a-3b35933576e0","eClass":"sysml:ParameterMembership","data":{"elementId":"55d9251d-9722-4f1f-ade8-5cce8d7bafb1","ownedRelatedElement":[{"id":"a6e4adef-1a08-4384-880e-95da452d581a","eClass":"sysml:Feature","data":{"elementId":"d1eb3702-b4d0-48d4-90df-5354359f0d33","ownedRelationship":[{"id":"ce942576-087e-4f35-a0a3-7c23a7fe2bb0","eClass":"sysml:FeatureValue","data":{"elementId":"303c1de0-a072-43e8-b687-38527c51eb0e","ownedRelatedElement":[{"id":"83bc616a-bfb5-4777-a169-ac1f8142d2aa","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"046cd544-1c5c-450f-8fac-3077ff9d3652","ownedRelationship":[{"id":"ea9f50bb-2fc9-4934-b613-79a4bdf9ab0f","eClass":"sysml:Membership","data":{"elementId":"8f01928c-b0c1-4056-bfbb-64ca3335b251","memberElement":"15ccc1e3-16b9-4ddf-9959-43141f32d48e"}}]}}]}}],"direction":"in"}}]}},{"id":"7b4f5c1d-fbcd-4074-89bc-6928aecb206f","eClass":"sysml:ParameterMembership","data":{"elementId":"5ac072c4-4955-4803-b651-4d14c001f97e","ownedRelatedElement":[{"id":"41a595a8-9dfb-4542-936b-ba98891a4ea9","eClass":"sysml:Feature","data":{"elementId":"6f135276-6932-4db1-bd9c-126cb8475498","ownedRelationship":[{"id":"fb8829dc-0d44-4004-b7c6-2d617de26808","eClass":"sysml:FeatureValue","data":{"elementId":"73c691d9-1ad0-4357-92ae-8e02e690f5ef","ownedRelatedElement":[{"id":"15f2308f-9b14-4c40-b6a9-d496987dfc8b","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"45435f31-674c-40aa-ad49-ce170852a12b","ownedRelationship":[{"id":"78ed96c8-cc8b-488d-8970-524f4a8bd5be","eClass":"sysml:Membership","data":{"elementId":"5229ec54-8bd3-49e2-8221-a5f8a76142cc","memberElement":"89b903a2-10c2-42a7-8307-b8bc9a4ba76a"}}]}}]}}],"direction":"in"}}]}}],"operator":"<="}}]}}],"isComposite":true}}]}}]}}]}},{"id":"2c772a21-cd4b-472b-b9cb-2d291b86eff3","eClass":"sysml:OwningMembership","data":{"elementId":"2fcf9e17-3424-4677-b324-314c82774361","ownedRelatedElement":[{"id":"3f2124ff-5c56-486b-a296-b1c3476e5180","eClass":"sysml:PartDefinition","data":{"declaredName":"Sensor","elementId":"024ec40b-3a5b-46df-add7-4bcbec5523c7","ownedRelationship":[{"id":"560c46bc-4057-4b9e-8e5a-49e9e4109d05","eClass":"sysml:FeatureMembership","data":{"elementId":"7c0bc2eb-1488-4dd8-8ab9-afadef79a367","ownedRelatedElement":[{"id":"94c0a654-c5dc-4579-a655-89edda340104","eClass":"sysml:AttributeUsage","data":{"declaredName":"label","elementId":"46235c7e-3f38-4dfa-a061-fa5662c9ac1e","ownedRelationship":[{"id":"1758c3f6-d099-452d-8c1b-b375d51491fc","eClass":"sysml:FeatureValue","data":{"elementId":"4d70b01b-05c6-4646-b564-2035f4bde5be","ownedRelatedElement":[{"id":"ec30e68f-b6c2-4ab8-af03-9fea9ceaf2e3","eClass":"sysml:LiteralString","data":{"elementId":"1d905119-2ad9-41e5-8896-7c0d3f166e2b","value":"unnamed"}}]}},{"id":"6fd57c7e-3d50-49b3-94b7-133020804fc4","eClass":"sysml:FeatureTyping","data":{"elementId":"2a1b98bf-116f-44b6-a5cb-8aff68c8e1a8","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#76028d3d-69a4-5e12-9002-ce403e0244bd","typedFeature":"94c0a654-c5dc-4579-a655-89edda340104"}}],"isComposite":true}}]}},{"id":"ea09c1cf-a6fb-41a4-9a32-07f9a59d6ef4","eClass":"sysml:FeatureMembership","data":{"elementId":"c23a7f58-2c6b-45c3-bc49-1944baf5face","ownedRelatedElement":[{"id":"edc4f7bc-7d24-498e-8e76-ae1743668254","eClass":"sysml:AttributeUsage","data":{"declaredName":"enabled","elementId":"2aa70e33-7074-4c1d-8ef7-af6874857071","ownedRelationship":[{"id":"8cd41188-d199-4c49-ad23-10e366344c35","eClass":"sysml:FeatureValue","data":{"elementId":"7ea1ae0f-9769-4a93-8523-1b544171ffb4","ownedRelatedElement":[{"id":"5669db5e-ec61-40ca-9a52-8979126921d0","eClass":"sysml:LiteralBoolean","data":{"elementId":"14630a78-98b4-4a46-ac40-c8a49a7b7390","value":true}}]}},{"id":"2afde92b-9d7f-4e1c-ab29-bc9bd2967a82","eClass":"sysml:FeatureTyping","data":{"elementId":"0daf88b8-e462-482b-8220-4f19e3ce8380","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#d1e9242d-b2e3-5270-bf69-4f4fb0447193","typedFeature":"edc4f7bc-7d24-498e-8e76-ae1743668254"}}],"isComposite":true}}]}},{"id":"18f6bc41-fa40-4f81-b741-d601365a37a0","eClass":"sysml:FeatureMembership","data":{"elementId":"2b9522eb-72fb-4e5b-aed4-99209a770f92","ownedRelatedElement":[{"id":"b922024b-5587-4be6-9924-6afa52ce8bf2","eClass":"sysml:AttributeUsage","data":{"declaredName":"samplingRate","elementId":"ddec4b3c-42e0-4d8e-bd99-304def079d94","ownedRelationship":[{"id":"985de5ed-784f-465e-805b-6b7d88b3bddc","eClass":"sysml:FeatureValue","data":{"elementId":"5bb61755-a54e-4ea0-9ec7-e11adf867185","ownedRelatedElement":[{"id":"6d57d690-633a-4018-a0f6-5e732bc16897","eClass":"sysml:LiteralRational","data":{"elementId":"e5ef69e1-5daf-4dae-b0ed-1e7903b3d079","value":100.0}}]}},{"id":"0929e1d2-a563-4e37-befc-02767a3165ea","eClass":"sysml:FeatureTyping","data":{"elementId":"17f59ceb-baef-48a4-b67b-934ed58da6bf","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}],"isComposite":true}}]}},{"id":"48904b34-6744-4d90-8ea3-f8388f930416","eClass":"sysml:FeatureMembership","data":{"elementId":"a7691d9d-0037-4942-8a83-92cc93f14d7d","ownedRelatedElement":[{"id":"2f50920f-47d5-4508-a943-33f9a2d56a23","eClass":"sysml:AttributeUsage","data":{"declaredName":"channelCount","elementId":"4c2b5049-e9d0-4573-8fb7-032cbdcf8fdb","ownedRelationship":[{"id":"14910b2a-ff6e-4f7e-bb13-7e0979c49eca","eClass":"sysml:FeatureValue","data":{"elementId":"2d3e55d0-a26b-4a6b-ac99-f049047ada35","ownedRelatedElement":[{"id":"36055b10-a46d-42c9-95c2-901d02b7490a","eClass":"sysml:LiteralInteger","data":{"elementId":"4525ba90-45e6-4bb4-9a44-a2b3766560e8","value":4}}]}},{"id":"ffed96db-63ef-4e40-b41d-080f7dc68fef","eClass":"sysml:FeatureTyping","data":{"elementId":"c0034730-d919-4a37-ac87-9fc378662a0b","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"2f50920f-47d5-4508-a943-33f9a2d56a23"}}],"isComposite":true}}]}},{"id":"6292da99-b47c-48f9-8d1b-9115b1b0c4e9","eClass":"sysml:FeatureMembership","data":{"elementId":"c7efeeab-923d-42bc-9d62-8bf61c2ab2d7","ownedRelatedElement":[{"id":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9","eClass":"sysml:AttributeUsage","data":{"declaredName":"currentValue","elementId":"855d423f-5dbb-4042-b98c-5a34602b1d0e","ownedRelationship":[{"id":"d9b556a4-b6eb-4e20-90f6-e63908599859","eClass":"sysml:FeatureValue","data":{"elementId":"25fc714d-8228-45f3-98c1-d154cf129985","ownedRelatedElement":[{"id":"ba6195b6-3db6-410a-bf38-a22204c4263e","eClass":"sysml:LiteralRational","data":{"elementId":"31e7ced7-a849-497a-8bea-9e58b3969239"}}],"isInitial":true}},{"id":"0d5731f8-b287-4a2d-854b-32292f6082e2","eClass":"sysml:FeatureTyping","data":{"elementId":"9bb1f845-d859-45d9-b375-8749b0e46272","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}],"isComposite":true}}]}},{"id":"47e0493d-48fd-4a90-977b-f159c2e2dafe","eClass":"sysml:FeatureMembership","data":{"elementId":"7171788a-abcf-4895-8770-192412a650a6","ownedRelatedElement":[{"id":"4d2f8465-d748-4b68-a5a8-d61c03031bd3","eClass":"sysml:AttributeUsage","data":{"declaredName":"errorCount","elementId":"bfc48daf-6923-48f1-9d09-596579985dab","ownedRelationship":[{"id":"c0caf7ee-94b3-44f0-a03b-13c5bfa2f37a","eClass":"sysml:FeatureValue","data":{"elementId":"99cec056-4306-4921-805d-140ecc9ee5de","ownedRelatedElement":[{"id":"0e18cf3c-0d0f-4863-b4e2-407a9fcdad8c","eClass":"sysml:LiteralInteger","data":{"elementId":"cb488158-7555-424f-a37d-1c290aa3cee5"}}],"isInitial":true}},{"id":"96a56407-061b-4f40-81f5-4d8f5e211b56","eClass":"sysml:FeatureTyping","data":{"elementId":"db1c53ba-8888-4645-bbd1-4624a258a238","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"4d2f8465-d748-4b68-a5a8-d61c03031bd3"}}],"isComposite":true}}]}},{"id":"2b4f3de5-32fd-4859-9fe6-5689e017c120","eClass":"sysml:FeatureMembership","data":{"elementId":"24b2ddc3-2007-4fcd-a4b7-943e1bc43948","ownedRelatedElement":[{"id":"3f6b7e75-5039-485c-9fbc-776b772cd746","eClass":"sysml:AttributeUsage","data":{"declaredName":"active","elementId":"251cc6ef-d2c6-4893-941c-076709500c76","ownedRelationship":[{"id":"2ba77e81-8da1-4fdc-ba91-163988a8862a","eClass":"sysml:FeatureValue","data":{"elementId":"457e68ff-f795-4dd9-8643-2dd851d2387a","ownedRelatedElement":[{"id":"0e79ab60-92de-43dc-8aed-85bd61eaa2b7","eClass":"sysml:LiteralBoolean","data":{"elementId":"79052415-268e-41f4-8cf6-ac6484067e91"}}],"isInitial":true}},{"id":"bcd180b6-ecd8-47fc-8f28-08095cd9e23f","eClass":"sysml:FeatureTyping","data":{"elementId":"09b93323-05a1-429c-9dac-dc2672085d02","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#d1e9242d-b2e3-5270-bf69-4f4fb0447193","typedFeature":"3f6b7e75-5039-485c-9fbc-776b772cd746"}}],"isComposite":true}}]}}]}}]}},{"id":"0f77318f-48df-4fd5-b4fe-c2470070695a","eClass":"sysml:OwningMembership","data":{"elementId":"3f6dda74-d5cc-4bc5-b728-79fd8dc7a929","ownedRelatedElement":[{"id":"2efcf5d4-4948-4b7d-b779-f3f694eb8165","eClass":"sysml:StateDefinition","data":{"declaredName":"ThermalControl","elementId":"040718ea-26b5-47d6-ba84-9f7c43fe2c07","ownedRelationship":[{"id":"6bd335ce-5089-4089-902f-917b1b6fed36","eClass":"sysml:StateSubactionMembership","data":{"elementId":"ded89b53-c1f0-4c68-8a56-d7283bc2b862","ownedRelatedElement":[{"id":"ac85c0b8-2d5a-491f-81dc-fb9b09b3ab31","eClass":"sysml:ActionUsage","data":{"elementId":"fd138068-384e-4be8-b885-ef3b218e006f","isComposite":true}}],"kind":"entry"}},{"id":"0345c054-7f57-45ec-8473-1261313b14d6","eClass":"sysml:FeatureMembership","data":{"elementId":"ea20286f-4020-4488-bfdd-f8b8c0293486","ownedRelatedElement":[{"id":"0a63014b-116e-455e-85f5-bc66c922d691","eClass":"sysml:TransitionUsage","data":{"elementId":"ddef46f5-05d7-411e-b826-3f1f3fea21ff","ownedRelationship":[{"id":"baa2a68d-e8f5-470c-b497-eda44fe94d59","eClass":"sysml:Membership","data":{"elementId":"0ea170b2-1597-4c55-b3e8-6cf8b7a9d204","memberElement":"ac85c0b8-2d5a-491f-81dc-fb9b09b3ab31"}},{"id":"0e6d29f8-3a63-48d1-af12-339e173ae602","eClass":"sysml:OwningMembership","data":{"elementId":"f5f627e0-538f-4fd9-b64b-a14966f22482","ownedRelatedElement":[{"id":"c59c0174-da0a-4972-a5ca-6743ab295651","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"f55e815c-45ae-4320-9753-a362b3c8e6e5","ownedRelationship":[{"id":"38f392ae-b052-4618-8c6d-8c01e635a521","eClass":"sysml:EndFeatureMembership","data":{"elementId":"8f15832d-752e-417c-a176-520904b7dfe1","ownedRelatedElement":[{"id":"a2b00582-c35c-41cf-86c2-49ab6a853807","eClass":"sysml:ReferenceUsage","data":{"elementId":"293900dd-1f99-49d4-8638-8c541b96ed6b","isEnd":true}}]}},{"id":"bf9eb61a-6c2d-4a2e-af99-6aec971b7e95","eClass":"sysml:EndFeatureMembership","data":{"elementId":"067cb51a-1f7b-40ad-b4e2-12b298e85ccc","ownedRelatedElement":[{"id":"76806c6d-2d0a-4dc0-9e1c-23dfe0845699","eClass":"sysml:ReferenceUsage","data":{"elementId":"7413373c-e4ea-4187-bcbe-e4f93128dab3","ownedRelationship":[{"id":"e57840d9-94d8-4186-8bbc-e56d0b5532d9","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"2a9d2963-2b80-4ed3-8daf-6b3637ed343c","subsettingFeature":"76806c6d-2d0a-4dc0-9e1c-23dfe0845699","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"1912dc94-522f-4d2a-9b1b-84ca3d86491e","eClass":"sysml:ParameterMembership","data":{"elementId":"4c276cae-1333-4c4d-a0fc-609b74b86cd6","ownedRelatedElement":[{"id":"43bed746-a5d8-4961-9fa3-560b9e53d921","eClass":"sysml:ReferenceUsage","data":{"elementId":"9e08b023-69df-4262-92be-ce2b9c6339a0","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"560d42e6-c398-48cf-9816-1bd9cae87041","eClass":"sysml:FeatureMembership","data":{"elementId":"4b970e61-3c84-4cf2-9c1f-ea3ef53bb346","ownedRelatedElement":[{"id":"630f2641-b66a-4f52-91c6-057b1c5811d0","eClass":"sysml:StateUsage","data":{"declaredName":"normal","elementId":"59276fa3-50b8-45da-a7d0-1775b3632476","isComposite":true}}]}},{"id":"e1a46bc4-adad-4ecd-ac1f-ec293b4466da","eClass":"sysml:FeatureMembership","data":{"elementId":"ca2e7bf0-9cee-4679-b29c-60eeadc8f7c1","ownedRelatedElement":[{"id":"9390334a-f844-4352-91a5-f0fbcfa072f7","eClass":"sysml:StateUsage","data":{"declaredName":"heating","elementId":"502e583f-266e-4e03-82d5-9198951b9736","isComposite":true}}]}},{"id":"4486dadb-f285-43a9-b554-b5dbe1f30ec4","eClass":"sysml:FeatureMembership","data":{"elementId":"a87c855f-cbc1-441a-90f9-59427af39f5c","ownedRelatedElement":[{"id":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd","eClass":"sysml:StateUsage","data":{"declaredName":"cooling","elementId":"336fbd96-f982-4f5f-ba7b-611ca08daa02","isComposite":true}}]}},{"id":"b7c0db78-1dfc-4f68-aa58-72a367032fca","eClass":"sysml:FeatureMembership","data":{"elementId":"5027456b-92a5-468a-8dc3-4da4d77356e5","ownedRelatedElement":[{"id":"8e205929-279c-421f-b739-c4d498c114da","eClass":"sysml:AttributeUsage","data":{"declaredName":"currentTemp","elementId":"5e7f955d-d275-4a9f-a4f6-fd91e00c903a","ownedRelationship":[{"id":"5be10aa2-0fcf-4b76-81bc-c700d3889d97","eClass":"sysml:FeatureValue","data":{"elementId":"f590f069-37c2-4b72-b412-0c004e7b3969","ownedRelatedElement":[{"id":"d0dec34a-5aca-420e-b7d6-4530d7ca54b2","eClass":"sysml:LiteralRational","data":{"elementId":"22502ad2-6755-4a78-b001-ae7d823d7a1a","value":20.0}}],"isInitial":true}},{"id":"7f7aafa0-3fc2-4cb5-9aa0-81039d5d4a51","eClass":"sysml:FeatureTyping","data":{"elementId":"fdb43bab-e1cc-4c65-966d-8242a09d6c52","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"8e205929-279c-421f-b739-c4d498c114da"}}],"isComposite":true}}]}},{"id":"a6e0b47d-eb19-4328-b6d6-99e68bfed356","eClass":"sysml:FeatureMembership","data":{"elementId":"9fc5a32e-ece4-4122-bed7-51fc54c19ba1","ownedRelatedElement":[{"id":"541bd9c9-44fa-4440-bebc-3f84820674e8","eClass":"sysml:AttributeUsage","data":{"declaredName":"targetTemp","elementId":"2a8602b9-d12d-40a2-9ca4-eeb421a9e2ed","ownedRelationship":[{"id":"e375b8ff-ef56-407b-8538-52a31352d147","eClass":"sysml:FeatureValue","data":{"elementId":"b63a0860-3159-44cc-922e-e4e962e48d91","ownedRelatedElement":[{"id":"2c01bf77-f6e4-4677-92c3-945189119f2e","eClass":"sysml:LiteralRational","data":{"elementId":"1d6f8b13-f67a-4508-9514-0fdd42ce7a11","value":22.0}}]}},{"id":"de665ea7-84c3-4e42-9a77-f593fe17b134","eClass":"sysml:FeatureTyping","data":{"elementId":"46004252-bb31-4407-9d4d-1e02857d777e","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}],"isComposite":true}}]}},{"id":"8d07b2dd-cb18-4fc0-baa8-f651b807b46c","eClass":"sysml:FeatureMembership","data":{"elementId":"485d35c7-55b7-4e7c-807b-0c65402c854c","ownedRelatedElement":[{"id":"9e405dc0-36d0-47f8-8b8d-461ab5a31169","eClass":"sysml:AttributeUsage","data":{"declaredName":"tolerance","elementId":"c79fd2f6-b87e-45ab-a978-d6e365d1892b","ownedRelationship":[{"id":"30f1fde2-4f4b-4257-8a9d-851f11cc8e6f","eClass":"sysml:FeatureValue","data":{"elementId":"e8a2a7c8-3eb0-4eca-af46-8812cde65a6a","ownedRelatedElement":[{"id":"ae8ef32c-b7d9-4f25-992d-8abc484db859","eClass":"sysml:LiteralRational","data":{"elementId":"ea074070-969d-4a48-b05b-afed056dab84","value":1.0}}]}},{"id":"d4ff4acb-0756-4348-8f5a-ff6f5a4fed41","eClass":"sysml:FeatureTyping","data":{"elementId":"50c766d5-c266-474b-9c43-d2cc1c0c498d","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#14c0aa22-5489-59b5-b438-ded26e83ba31","typedFeature":"9e405dc0-36d0-47f8-8b8d-461ab5a31169"}}],"isComposite":true}}]}},{"id":"7656692f-d1a8-4b63-9969-0191adc8273e","eClass":"sysml:FeatureMembership","data":{"elementId":"d8e1cc5d-5bfb-4195-91db-318eeb0b2706","ownedRelatedElement":[{"id":"0b517687-ef3f-4057-9ce5-27e27f627a22","eClass":"sysml:TransitionUsage","data":{"declaredName":"to_heating","elementId":"722d9bb6-f15a-4133-9baa-5d87384af8b2","ownedRelationship":[{"id":"ad20395d-9921-44c2-8311-8afdcdf04157","eClass":"sysml:Membership","data":{"elementId":"1d757d16-ec70-4b47-a753-7dd9402e02bc","memberElement":"630f2641-b66a-4f52-91c6-057b1c5811d0"}},{"id":"e361c51a-2480-42e1-a181-ce7d079b2e93","eClass":"sysml:OwningMembership","data":{"elementId":"c2b19814-61f6-4e6e-938f-9cf8dd68ef62","ownedRelatedElement":[{"id":"8085cacc-ccab-4176-91bc-f90d138bf7f3","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"25f126b9-bc1f-43b5-8f65-6c11f41c569b","ownedRelationship":[{"id":"bc9dc7b9-9b80-4c4d-80e8-b137d62abf73","eClass":"sysml:EndFeatureMembership","data":{"elementId":"99db0664-a0b4-4ea0-87eb-cb801838d5fe","ownedRelatedElement":[{"id":"93e43e08-43e2-4c01-b101-436fefc0feb7","eClass":"sysml:ReferenceUsage","data":{"elementId":"430bfb97-e843-4c1d-9351-ed828370dcbc","isEnd":true}}]}},{"id":"45680a1a-a4e5-4f8b-933a-2f87141422ce","eClass":"sysml:EndFeatureMembership","data":{"elementId":"cdb2a753-f470-47a3-b073-f980d304fb23","ownedRelatedElement":[{"id":"7fd10dad-a085-472c-b06d-3173f81373b0","eClass":"sysml:ReferenceUsage","data":{"elementId":"28801261-d808-4b8b-a9c4-849aa076620f","ownedRelationship":[{"id":"ca8fd8cd-1fd0-4936-a7e8-474780da6295","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"6bf78264-9a29-4a7d-9f58-af4519b5a245","subsettingFeature":"7fd10dad-a085-472c-b06d-3173f81373b0","referencedFeature":"9390334a-f844-4352-91a5-f0fbcfa072f7"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"50ce6fd3-4386-43e7-9c79-92791f484058","eClass":"sysml:ParameterMembership","data":{"elementId":"4b1fa532-9975-475f-b7a3-2b8dccde5efa","ownedRelatedElement":[{"id":"a50dc602-495e-4cbf-8587-a7909d1e064d","eClass":"sysml:ReferenceUsage","data":{"elementId":"918f482a-795f-4158-9f1b-16f94c2cfb4a","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"211a29e1-2104-4473-bc7a-e7675162e447","eClass":"sysml:FeatureMembership","data":{"elementId":"30842099-ac84-4baf-aae8-d78c11ba491a","ownedRelatedElement":[{"id":"e1c27d0b-476e-42d4-9b81-b5f064d9cbbe","eClass":"sysml:TransitionUsage","data":{"declaredName":"to_cooling","elementId":"3df50466-18d3-48d1-9b1a-6b35ab79f2b7","ownedRelationship":[{"id":"6971555b-4116-48f0-9847-9292f1357d54","eClass":"sysml:Membership","data":{"elementId":"1ae63504-5879-44d8-845c-58145c66cee8","memberElement":"630f2641-b66a-4f52-91c6-057b1c5811d0"}},{"id":"2f3331f5-bbe1-44c4-844b-d24c8f2eeffb","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"f0e1ee9a-8235-4875-b5e3-1ff7f8ac8a85","ownedRelatedElement":[{"id":"ec67ead5-7739-4dd3-a82e-f1bb5ef34268","eClass":"sysml:OperatorExpression","data":{"elementId":"974ce809-d343-4a2f-8fe5-cec41eb46ba4","ownedRelationship":[{"id":"371effd8-5eea-4802-94e5-704498a68b13","eClass":"sysml:ParameterMembership","data":{"elementId":"bc3ab140-50b6-4c33-9874-23ebc399610c","ownedRelatedElement":[{"id":"40353cdf-d10b-4322-b623-05972ba837e3","eClass":"sysml:Feature","data":{"elementId":"664143da-4921-42a1-9cfd-cfc893719859","ownedRelationship":[{"id":"1eea43cc-f48e-4dc3-bf5d-574dd7fadcb9","eClass":"sysml:FeatureValue","data":{"elementId":"4f6f4e36-88e9-4ce7-b53f-2bb46878a9f3","ownedRelatedElement":[{"id":"1440ba96-39f9-4745-9596-625baab83480","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"a06418d2-453e-4ea7-90c6-cedb31a54a93","ownedRelationship":[{"id":"3af419a1-d8cd-4f4e-a95f-03d88df310c5","eClass":"sysml:Membership","data":{"elementId":"94b074ff-c911-4b46-838c-d617bc424d2d","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"b6bbf397-915c-4df2-8153-046eddf48b60","eClass":"sysml:ParameterMembership","data":{"elementId":"1c049222-6ff6-4835-a00a-8df9349d8266","ownedRelatedElement":[{"id":"e73a1795-d083-4539-953e-6ce302c9c7a0","eClass":"sysml:Feature","data":{"elementId":"4b579ae4-8c79-4c88-9b21-db059d7857b7","ownedRelationship":[{"id":"74a4b0ca-269e-480b-b209-5a36bcfcad18","eClass":"sysml:FeatureValue","data":{"elementId":"5a8e236c-908c-478f-94a4-1dccce775e9f","ownedRelatedElement":[{"id":"c656679c-b3f8-4218-8b7c-94f40c432e9e","eClass":"sysml:OperatorExpression","data":{"elementId":"e7eac6ca-3967-41af-8f50-de765b9e7c87","ownedRelationship":[{"id":"90b4fda8-1e61-4157-966d-60ebaa3cecaa","eClass":"sysml:ParameterMembership","data":{"elementId":"8dfcdc00-48ae-4f73-b096-74263b2ff799","ownedRelatedElement":[{"id":"c612b8d5-4885-4c2e-85ed-6d0ad2074202","eClass":"sysml:Feature","data":{"elementId":"c1768702-c8ce-41c2-8c51-8195d64c97b6","ownedRelationship":[{"id":"03915a4e-b0da-48e8-863f-30f53ac37cea","eClass":"sysml:FeatureValue","data":{"elementId":"b00bb56f-0b71-407c-baa4-90956eb99b76","ownedRelatedElement":[{"id":"13070906-e608-4e8d-8418-3fc3916128f0","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"882ab32c-e241-4989-955c-608a9acbae32","ownedRelationship":[{"id":"9726f328-2238-44c6-b640-29ebad59d238","eClass":"sysml:Membership","data":{"elementId":"bc37097c-d761-4b2d-b506-9c807f25c907","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}},{"id":"3d67e9aa-3fc0-4e48-a7a0-632f6b5730c1","eClass":"sysml:ParameterMembership","data":{"elementId":"a56ba801-d9c5-4302-99ae-d5e68376378c","ownedRelatedElement":[{"id":"870fc619-a861-4d71-8b0d-4c700c8c4b3f","eClass":"sysml:Feature","data":{"elementId":"bd432a49-148b-4805-b314-6aaa2b485eba","ownedRelationship":[{"id":"db0aabd1-5712-4faa-86b7-4bd4176b4389","eClass":"sysml:FeatureValue","data":{"elementId":"9702fb41-ed29-4393-bbba-8c6b864eb4e0","ownedRelatedElement":[{"id":"edc353c4-b66d-4b2b-b8d5-55f8246922ab","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"82a521eb-14f5-4e56-be04-49bb2a83678d","ownedRelationship":[{"id":"7e2b0f6f-6c10-4670-aa85-2294aadb7be3","eClass":"sysml:Membership","data":{"elementId":"225dfdb5-3b07-4afd-bb2d-554318c82ed5","memberElement":"9e405dc0-36d0-47f8-8b8d-461ab5a31169"}}]}}]}}],"direction":"in"}}]}}],"operator":"+"}}]}}],"direction":"in"}}]}}],"operator":">"}}],"kind":"guard"}},{"id":"f2dd1298-dec2-44c6-bccc-c6aff0942073","eClass":"sysml:OwningMembership","data":{"elementId":"c405c6cb-696d-4a3f-99e7-6dab852ae228","ownedRelatedElement":[{"id":"c4e5cb98-07df-49a6-a3b1-93e9d9d6f4f5","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"acd50047-bcc8-421f-b204-cef2c540355e","ownedRelationship":[{"id":"73144371-94ed-44bb-95ab-70a1a23360fe","eClass":"sysml:EndFeatureMembership","data":{"elementId":"697afe9a-c1f3-4c65-a063-7bc9ab4b106d","ownedRelatedElement":[{"id":"220c6106-c36f-4497-88e2-42125a9f69d5","eClass":"sysml:ReferenceUsage","data":{"elementId":"b1438ef2-513a-43b5-a292-7e34cd24f941","isEnd":true}}]}},{"id":"39c31f59-67df-408c-bf92-9b1c9dc209df","eClass":"sysml:EndFeatureMembership","data":{"elementId":"7e270dc1-76ee-4023-9d55-128523dd8d26","ownedRelatedElement":[{"id":"9dd8948f-9a7c-4682-bc46-dda6eaf7eed8","eClass":"sysml:ReferenceUsage","data":{"elementId":"8a705bce-88f0-4558-b010-cac84b264413","ownedRelationship":[{"id":"16928b68-0b7c-4da8-891f-bf6fc174361a","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"36718153-4eb3-48ca-8023-b1ca8a606897","subsettingFeature":"9dd8948f-9a7c-4682-bc46-dda6eaf7eed8","referencedFeature":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"6b679136-5121-49fc-b63f-edea84f72f73","eClass":"sysml:ParameterMembership","data":{"elementId":"9d7e2288-1a5a-4ad9-aa04-96f72ddca831","ownedRelatedElement":[{"id":"5d11e636-89f5-4d42-a233-207b6d62d418","eClass":"sysml:ReferenceUsage","data":{"elementId":"8ffbe3d2-f907-4fd2-b2b3-c67ac8ef75bd","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"da3ff9dc-93bb-406a-a2cb-6bb17b551a62","eClass":"sysml:FeatureMembership","data":{"elementId":"6cf8e042-d8f9-41b6-9a1d-3232943b2b14","ownedRelatedElement":[{"id":"c7efc3c8-830f-41f4-a9cb-a3667f7c7637","eClass":"sysml:TransitionUsage","data":{"declaredName":"heating_done","elementId":"6bb2e424-424c-44d4-afb6-3923e8202303","ownedRelationship":[{"id":"c2f144d8-86b6-4dd7-b2ff-7280703d9e5d","eClass":"sysml:Membership","data":{"elementId":"551669f0-c179-4998-8de3-84a03f2255b4","memberElement":"9390334a-f844-4352-91a5-f0fbcfa072f7"}},{"id":"6dac8578-e793-4cc2-9581-59c2ef40532c","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"cf32b8b1-18ec-4787-9eb0-95da2eeb675a","ownedRelatedElement":[{"id":"e9f31b7a-9673-4037-859b-7d6e5775db53","eClass":"sysml:OperatorExpression","data":{"elementId":"514158d0-9ec0-4ca8-8cf6-c201eded035b","ownedRelationship":[{"id":"2b0b4608-771a-4b49-8264-ee9022d5f533","eClass":"sysml:ParameterMembership","data":{"elementId":"c32a9d2f-ed2f-442c-9eef-7f282e73f828","ownedRelatedElement":[{"id":"f9b860f0-3ab9-4b35-a5af-7b87c85aa51a","eClass":"sysml:Feature","data":{"elementId":"be79d529-4b62-4620-96f6-151347ef888a","ownedRelationship":[{"id":"06a57d10-f450-4edc-8d6d-7e9c085d5678","eClass":"sysml:FeatureValue","data":{"elementId":"b8b2fe56-0ab6-41c9-ab2a-fc9f238d4c36","ownedRelatedElement":[{"id":"07ecaa6c-9469-4602-9938-ef4fe35c8e61","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"498a0218-a6a1-4d1d-951d-b9f2fb76a93a","ownedRelationship":[{"id":"2a962769-9796-46c5-a084-e78784f6e775","eClass":"sysml:Membership","data":{"elementId":"4cf777d6-945d-407c-a1ed-e0b1af63fe54","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"925a2b9f-4c32-49a1-9b83-23b44f262ae8","eClass":"sysml:ParameterMembership","data":{"elementId":"2b1b4a8e-8d3e-4611-9e2b-e67fb634a03c","ownedRelatedElement":[{"id":"2a0e96be-a356-424d-a497-1fb6e0a67a75","eClass":"sysml:Feature","data":{"elementId":"b118b738-974f-47c8-9000-e676ff11acf9","ownedRelationship":[{"id":"77fa7bc6-7751-48fd-b4db-811e8ddb0107","eClass":"sysml:FeatureValue","data":{"elementId":"0faa3816-569c-44c2-91f4-0a62629bdc35","ownedRelatedElement":[{"id":"8deba717-e9e8-4359-a7ee-0392cc60da28","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4f0cbbb1-ed40-47c5-9fdc-716954416eca","ownedRelationship":[{"id":"31c29b60-785d-4c12-91ff-1a6bd5cd0a97","eClass":"sysml:Membership","data":{"elementId":"cfb554e6-b753-40aa-8212-646ac2307d97","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}}],"operator":">="}}],"kind":"guard"}},{"id":"52bd3814-e962-4bf3-bdbc-af103344c0ad","eClass":"sysml:OwningMembership","data":{"elementId":"68dca418-736b-429d-b442-271730f62bed","ownedRelatedElement":[{"id":"bf42847e-36cd-4d3d-aa5f-adbda8deedf1","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"1235177c-931e-444e-841a-74a0033b7573","ownedRelationship":[{"id":"71fc2ef3-58ee-46f5-9f59-16782d9d18ca","eClass":"sysml:EndFeatureMembership","data":{"elementId":"64387b5f-6f0c-43c6-8630-9f507376e5e3","ownedRelatedElement":[{"id":"445af89b-6f69-4a1b-bb66-ee2fad4012bd","eClass":"sysml:ReferenceUsage","data":{"elementId":"39473346-c45b-4bf0-a667-771e453ca497","isEnd":true}}]}},{"id":"853b2327-fd95-4281-92d3-39675c9832ff","eClass":"sysml:EndFeatureMembership","data":{"elementId":"ae636aba-2171-48b4-9bc9-36b8e319a679","ownedRelatedElement":[{"id":"b2b75688-a923-4a1f-966d-bacdff99b033","eClass":"sysml:ReferenceUsage","data":{"elementId":"a4debe8e-e4c5-4e03-ac70-94f40d27f9e9","ownedRelationship":[{"id":"43ce1363-6e62-4981-b36e-b8e0b32431f3","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"66ec302b-b8c2-4029-8536-830eeb9904ae","subsettingFeature":"b2b75688-a923-4a1f-966d-bacdff99b033","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"a4f9b12e-4854-450c-a5b4-c13417654040","eClass":"sysml:ParameterMembership","data":{"elementId":"46d97c31-de66-482e-91da-e7fbc6555f7a","ownedRelatedElement":[{"id":"f7e4f511-9110-424d-9787-c4bec859f3bb","eClass":"sysml:ReferenceUsage","data":{"elementId":"e1cdc0e3-a709-4173-9d58-7500c52b4d9f","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}},{"id":"fd55211f-bc7f-4598-8bc1-0a3d4b54f974","eClass":"sysml:FeatureMembership","data":{"elementId":"888f6364-e8aa-4312-8477-baa01db1b493","ownedRelatedElement":[{"id":"8a153941-bf0a-4010-a51e-62acb8bd63bb","eClass":"sysml:TransitionUsage","data":{"declaredName":"cooling_done","elementId":"9bb3b3d0-59ae-43ea-aeeb-27cd95233987","ownedRelationship":[{"id":"5a798e86-8ac9-428c-bd43-983a008a96ce","eClass":"sysml:Membership","data":{"elementId":"150daea0-ca87-4737-b1cc-be68c0708d45","memberElement":"1ff2edd1-7ecc-4711-8e0b-1d9e6ba18afd"}},{"id":"9a4869bf-59f1-40fe-bb41-5b80125eec95","eClass":"sysml:TransitionFeatureMembership","data":{"elementId":"0ee132d8-b870-40a6-93b2-0e386ca698ec","ownedRelatedElement":[{"id":"506f2589-c9aa-497d-b9e2-9f3568a1b60e","eClass":"sysml:OperatorExpression","data":{"elementId":"b17dcb88-0404-4a2d-b175-29b5c2430b10","ownedRelationship":[{"id":"9439080c-7bc5-442c-a234-4fbced1722fd","eClass":"sysml:ParameterMembership","data":{"elementId":"03eeff23-1ce5-40e9-b8f8-8c971d8fea9b","ownedRelatedElement":[{"id":"4bb65cfe-8311-4ac1-85d8-1b19421553b0","eClass":"sysml:Feature","data":{"elementId":"12652e9b-2669-4e27-90fb-3d6c3f3a665b","ownedRelationship":[{"id":"6ec15f89-da66-4dc9-bdf1-34a8235a0e60","eClass":"sysml:FeatureValue","data":{"elementId":"516566a3-89e8-4057-8bb4-3238a772efae","ownedRelatedElement":[{"id":"131bcb2c-6bd2-4e48-a392-4bc83d15ec5d","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"71069a61-0947-49ae-82a6-131855801506","ownedRelationship":[{"id":"3b4c7e1b-00ad-4ef4-8f12-87c642d7e340","eClass":"sysml:Membership","data":{"elementId":"b7da76e8-90dd-4816-a096-3bc4d74fcfff","memberElement":"8e205929-279c-421f-b739-c4d498c114da"}}]}}]}}],"direction":"in"}}]}},{"id":"4c107a4c-9209-412b-953e-60b1c643382a","eClass":"sysml:ParameterMembership","data":{"elementId":"4e92e729-b2d1-424c-9471-8f8c17cdc6b7","ownedRelatedElement":[{"id":"010203af-dce4-454e-a19a-888ae9c3b675","eClass":"sysml:Feature","data":{"elementId":"401748ba-f2fe-4fd0-903a-bbbfb3067510","ownedRelationship":[{"id":"4ba22430-f1f1-4462-a196-ed8b6e119841","eClass":"sysml:FeatureValue","data":{"elementId":"9854172d-ee15-4e79-9acd-9717b3b5c598","ownedRelatedElement":[{"id":"61a15a33-8067-4d16-a44f-73bf1eb99e2d","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"972b0f23-2c30-42c6-93d4-71b2d291460e","ownedRelationship":[{"id":"364f5f78-67b1-4631-9d0e-01641d95afc9","eClass":"sysml:Membership","data":{"elementId":"cfba9064-3b74-4bf4-bdbf-97e54c8b2013","memberElement":"541bd9c9-44fa-4440-bebc-3f84820674e8"}}]}}]}}],"direction":"in"}}]}}],"operator":"<="}}],"kind":"guard"}},{"id":"0f19e6b9-2973-411c-b800-8d0ed49795be","eClass":"sysml:OwningMembership","data":{"elementId":"d2755907-2b2e-452f-8051-637f99928b24","ownedRelatedElement":[{"id":"d8aee92a-f512-4762-b4e4-b948f450a024","eClass":"sysml:SuccessionAsUsage","data":{"elementId":"c1cb5168-b133-4e08-8f9f-3243ee80134d","ownedRelationship":[{"id":"9b1ee916-7707-43a1-937c-7cad3d9b5b77","eClass":"sysml:EndFeatureMembership","data":{"elementId":"1526df00-9a9b-41e4-8224-e54e782c429d","ownedRelatedElement":[{"id":"03e69081-de75-4755-8a05-056340bfcf21","eClass":"sysml:ReferenceUsage","data":{"elementId":"b907c9b6-3433-4113-9ed8-34644ca93a8c","isEnd":true}}]}},{"id":"f8423145-7a38-4e0b-848d-67a70db029c6","eClass":"sysml:EndFeatureMembership","data":{"elementId":"2595cd38-81ee-46c6-b87c-7c948a5ab166","ownedRelatedElement":[{"id":"98dfa1ca-9866-4079-b43d-b61af3c53e64","eClass":"sysml:ReferenceUsage","data":{"elementId":"ada1671c-beb1-4333-b144-1c9568840b05","ownedRelationship":[{"id":"629647f9-2a93-493e-883d-d5c0cb6d9fdd","eClass":"sysml:ReferenceSubsetting","data":{"elementId":"de396f89-7470-469c-9ab6-a726f8de8400","subsettingFeature":"98dfa1ca-9866-4079-b43d-b61af3c53e64","referencedFeature":"630f2641-b66a-4f52-91c6-057b1c5811d0"}}],"isComposite":true,"isEnd":true}}]}}],"isComposite":true}}]}},{"id":"5ed10d2c-ac2b-4864-9b4f-74218a8119d7","eClass":"sysml:ParameterMembership","data":{"elementId":"8444ae28-737f-4667-b584-a5ec3afd4cc5","ownedRelatedElement":[{"id":"3414baf1-cc30-4843-90e6-ed004d4b11f4","eClass":"sysml:ReferenceUsage","data":{"elementId":"a9f3e3d7-8086-467c-8a9f-040ae5ec8f4a","direction":"in","isComposite":true}}]}}],"isComposite":true}}]}}]}}]}},{"id":"f1ac0d22-7a0f-413b-b576-85a3ffbe6135","eClass":"sysml:OwningMembership","data":{"elementId":"e648c25f-e278-4e65-9133-0dc96e1f0026","ownedRelatedElement":[{"id":"69d595d7-6a07-4cb1-a4ea-e6102b4ec12d","eClass":"sysml:ConcernDefinition","data":{"declaredName":"SafetyAndReliability","elementId":"3c2ae026-8af6-4bf4-bc7c-79234a98eff9","ownedRelationship":[{"id":"ef1499c9-c7f7-4acb-acf5-e8877c9383c8","eClass":"sysml:FeatureMembership","data":{"elementId":"c610ab68-ac78-4599-b05e-7174225eeaa7","ownedRelatedElement":[{"id":"e2678e9c-3155-4570-bd56-4c8457084f05","eClass":"sysml:AttributeUsage","data":{"declaredName":"deploymentCount","elementId":"9c8fd285-2a30-4ee8-9e2b-cc5a38f03e85","ownedRelationship":[{"id":"3e8dbff8-89e0-4113-a368-9080e6e59b45","eClass":"sysml:FeatureValue","data":{"elementId":"7359a844-4139-4401-b296-a9ab08f92acf","ownedRelatedElement":[{"id":"2db9e19e-7b70-420f-bbab-875dd36ee56f","eClass":"sysml:LiteralInteger","data":{"elementId":"05d4dfe9-b7c6-4b85-864b-83f347eee7be","value":3}}]}},{"id":"21d2afe7-e7b0-4994-9dca-09221ba31bf1","eClass":"sysml:FeatureTyping","data":{"elementId":"c6132f83-494c-4a60-bbac-1862a5261fc7","type":"sysml:DataType kermllibrary:///b2c6dd37-2084-3ce4-9ce2-580fdf30629c#f2350199-2ab1-5258-8514-58812ef25dc6","typedFeature":"e2678e9c-3155-4570-bd56-4c8457084f05"}}],"isComposite":true}}]}},{"id":"5878dce7-7b5a-4f3f-9780-b01ccdd0c379","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"d788cb4d-7166-4e73-ac86-425afa925dec","ownedRelatedElement":[{"id":"5e36a9cd-89d3-4653-b767-0e1be2d32ad5","eClass":"sysml:ConstraintUsage","data":{"elementId":"585f8cab-50a5-47a5-8ea1-3f5929be4af2","ownedRelationship":[{"id":"821531fa-1c3b-468e-aeba-5f2f8ce6e2a4","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"a5488ef2-0227-4422-ac46-dda945fcbf4d","ownedRelatedElement":[{"id":"8a6c830c-98af-403f-a4de-938a31f61194","eClass":"sysml:OperatorExpression","data":{"elementId":"8f0efd41-c032-4a95-b4da-80641f15fa5a","ownedRelationship":[{"id":"298ac857-1424-421a-8895-f8b2ef5cfc55","eClass":"sysml:ParameterMembership","data":{"elementId":"337a51c2-5cb0-4c94-9309-06d838bdb875","ownedRelatedElement":[{"id":"b0ce01ae-8dd1-406b-b61e-6b5c0200a4bc","eClass":"sysml:Feature","data":{"elementId":"bed903ba-e17d-426e-bef1-3c83fed8ad5b","ownedRelationship":[{"id":"1489f1a6-db01-4f94-b7ba-3c221451fbbe","eClass":"sysml:FeatureValue","data":{"elementId":"294d19aa-e1a2-429a-a91e-35b068b48631","ownedRelatedElement":[{"id":"9e0eed6b-d20e-449a-b674-3e54e3d53859","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4affe832-9f21-4775-abf7-9e33ea8c6c8e","ownedRelationship":[{"id":"37daf8ad-f0b9-4ac1-96f1-29da588d1fe5","eClass":"sysml:Membership","data":{"elementId":"bf9614cb-198c-4f53-9f63-0f1aa8820c10","memberElement":"e2678e9c-3155-4570-bd56-4c8457084f05"}}]}}]}}],"direction":"in"}}]}},{"id":"f35b3dda-8d34-4dc3-94e0-e5f7a7accff9","eClass":"sysml:ParameterMembership","data":{"elementId":"2bd75866-58d5-4522-aca1-6cf4196ed16b","ownedRelatedElement":[{"id":"1eace1ad-8813-4660-a1cd-332909552774","eClass":"sysml:Feature","data":{"elementId":"bd79950f-6dbf-4c42-8f2c-06aa4b7744c6","ownedRelationship":[{"id":"64d75861-f3c8-44f3-a0b8-dbf2e7878dc3","eClass":"sysml:FeatureValue","data":{"elementId":"07085d12-61df-40fa-8768-49c55c23e67b","ownedRelatedElement":[{"id":"56c8f7f8-93ef-4666-aa56-53b6531c0d4f","eClass":"sysml:LiteralInteger","data":{"elementId":"1791dfbd-3e30-488c-bbbe-30816bad15bc"}}]}}],"direction":"in"}}]}}],"operator":">"}}]}}],"isComposite":true}}]}},{"id":"597a0e23-3eef-471c-8dbd-75562a4e4d7a","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"b0aef8c1-d38c-4bd9-8ae2-4f0542fe91d7","ownedRelatedElement":[{"id":"b34a95e4-cb32-4a1c-b1ee-17d4bd62c7d2","eClass":"sysml:ConstraintUsage","data":{"declaredName":"minimumRedundancy","elementId":"76a7a9b1-9ecc-42b1-9a41-5b328053f12f","ownedRelationship":[{"id":"8c80e3db-82fa-41c4-be21-274b737f7284","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"dbb57839-6678-448a-8221-be6911b0f848","ownedRelatedElement":[{"id":"ed00c629-0f82-4874-9590-5a775e35081d","eClass":"sysml:OperatorExpression","data":{"elementId":"c67dae08-fad7-409c-ae7b-ee013cca30d6","ownedRelationship":[{"id":"7d801324-bad9-46b1-970f-7a2b38a556aa","eClass":"sysml:ParameterMembership","data":{"elementId":"8a478841-dab9-42a1-8966-ed68ec3be498","ownedRelatedElement":[{"id":"dc503057-d95b-4569-b694-9c03d8a4a711","eClass":"sysml:Feature","data":{"elementId":"5ee82585-9fb8-4395-8b39-e9ffc2ac6d80","ownedRelationship":[{"id":"8c469bc4-c47f-4ea8-9b6d-2aa4c643d7c1","eClass":"sysml:FeatureValue","data":{"elementId":"e1671e98-bc6d-4194-84c8-6f79c29850c0","ownedRelatedElement":[{"id":"2d5735e7-8a41-4fd8-856e-46af848a86f0","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"7f2be62b-42dc-4161-bbf1-9e33a596e6f7","ownedRelationship":[{"id":"cf8e2ed0-00d1-4e87-8a2f-b23d7c6c2879","eClass":"sysml:Membership","data":{"elementId":"f11aecf9-0c21-45a8-843f-fe5d4d96a0a9","memberElement":"e2678e9c-3155-4570-bd56-4c8457084f05"}}]}}]}}],"direction":"in"}}]}},{"id":"6f077a43-6f45-49b1-9232-b3282f0abb57","eClass":"sysml:ParameterMembership","data":{"elementId":"c2c6e7b8-af06-4096-989a-3c2e95baca51","ownedRelatedElement":[{"id":"0309d85e-37cc-499f-b876-846b2d5a4c2a","eClass":"sysml:Feature","data":{"elementId":"ca1bdcc4-dadc-4228-8d61-813b74f39cc7","ownedRelationship":[{"id":"dfad1497-873d-4629-a277-c254e1a247a9","eClass":"sysml:FeatureValue","data":{"elementId":"a50bbd08-8668-4de4-a64f-016da901a339","ownedRelatedElement":[{"id":"d1b9e2c7-f50f-44a3-a585-7f531eb3fbf9","eClass":"sysml:LiteralInteger","data":{"elementId":"48a9725a-a225-454e-8421-a03542e9e7e8","value":2}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"isComposite":true}}],"kind":"requirement"}}]}}]}},{"id":"a6f07c1f-b22d-4081-a3d9-3fc78dee4d22","eClass":"sysml:OwningMembership","data":{"elementId":"db5e69df-ce41-43a4-a9c1-2655173fae74","ownedRelatedElement":[{"id":"da2296a4-25ed-4f04-abc8-d47f93cd223c","eClass":"sysml:ConcernDefinition","data":{"declaredName":"PerformanceConcern","elementId":"719defb0-780c-486b-85d5-b3d4e5b460cc","ownedRelationship":[{"id":"d1836f12-7281-4b5b-a0d2-26cfef749277","eClass":"sysml:SubjectMembership","data":{"elementId":"35bf0d61-c429-43fb-8f17-f6059aa0c4d3","ownedRelatedElement":[{"id":"33466a30-d081-4d0d-a3dc-142c59b82000","eClass":"sysml:ReferenceUsage","data":{"declaredName":"s","elementId":"ea6f2066-3a2f-4888-9eb8-33e6cec61b8d","ownedRelationship":[{"id":"1355d4f4-a4c7-4a0c-bb4a-a8dd29b2c3df","eClass":"sysml:FeatureTyping","data":{"elementId":"caea1502-7778-408f-ac2b-db317a07154f","type":"3f2124ff-5c56-486b-a296-b1c3476e5180","typedFeature":"33466a30-d081-4d0d-a3dc-142c59b82000"}}],"direction":"in","isComposite":true}}]}},{"id":"a4eda0c9-d3e4-4ebc-8d8b-0c864423acf4","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"fbab8f7d-eaf7-4510-bed3-2679d739229a","ownedRelatedElement":[{"id":"4fd2c402-15b7-4546-ad9c-7aa9419a1528","eClass":"sysml:ConstraintUsage","data":{"elementId":"98f1df4b-ff5c-498a-960b-9cb66ef0dbf9","isComposite":true}}]}},{"id":"934e8eac-2e71-4b04-b759-d928aee33336","eClass":"sysml:RequirementConstraintMembership","data":{"elementId":"df1c9c38-1d8b-49e6-b8f9-4cdc9af5b9d9","ownedRelatedElement":[{"id":"6891b4f5-6f02-4c73-ae23-db88ad10b253","eClass":"sysml:ConstraintUsage","data":{"declaredName":"responsiveness","elementId":"c0f01f9c-e59f-4517-9d2c-a295ce86c4b2","ownedRelationship":[{"id":"d20bfa80-aa30-436f-a5bf-96e2217efa58","eClass":"sysml:ResultExpressionMembership","data":{"elementId":"33ea9c9a-383c-4d7e-b356-6df68a277de9","ownedRelatedElement":[{"id":"6f2e1644-b09d-46a2-b155-fc123e0f2953","eClass":"sysml:OperatorExpression","data":{"elementId":"378814e3-5c6b-4aac-983b-56d7ba918c1d","ownedRelationship":[{"id":"93a8bf8c-3c78-47f4-be7a-5bfe2faccaa3","eClass":"sysml:ParameterMembership","data":{"elementId":"8b7301cd-24b5-4b2b-8e1a-5a0dc096bdbc","ownedRelatedElement":[{"id":"fb7b2c32-7fe5-4ad7-bf3c-fc17280e4f4b","eClass":"sysml:Feature","data":{"elementId":"5a5849ab-2fa4-4966-8981-e252afcbe1f8","ownedRelationship":[{"id":"3a8347bc-70f7-4de8-892f-676542d63765","eClass":"sysml:FeatureValue","data":{"elementId":"dc48009e-02ff-4dd9-8986-71bef33e499f","ownedRelatedElement":[{"id":"501238ee-b170-4a71-add9-c3cc4b62b541","eClass":"sysml:OperatorExpression","data":{"elementId":"b4f2d2fc-f450-48f8-ade1-138bedd954ab","ownedRelationship":[{"id":"0e53a9bd-1bd5-4b12-931c-da6a744381be","eClass":"sysml:ParameterMembership","data":{"elementId":"2eecf130-286c-498a-b073-6ccd04e790dd","ownedRelatedElement":[{"id":"244833c3-2b41-467a-bb18-03bdca1aaf91","eClass":"sysml:Feature","data":{"elementId":"35c7ccb4-753a-4b3b-8bee-1e87f1faba9d","ownedRelationship":[{"id":"c2125fb7-4da1-4c18-ae2d-545b2ca6e3d3","eClass":"sysml:FeatureValue","data":{"elementId":"09b48893-6827-4cf9-bec6-88b807844c19","ownedRelatedElement":[{"id":"c19dca8a-1bed-49cd-a027-c10b6570e483","eClass":"sysml:FeatureChainExpression","data":{"elementId":"7a3c3fe4-404d-4889-9e34-1a3dd5ce5ca5","ownedRelationship":[{"id":"2febd014-6a70-48ac-9a28-211fb0cfc2bb","eClass":"sysml:ParameterMembership","data":{"elementId":"57bc8b4b-0a38-4b7f-b3a6-5d0523cc728c","ownedRelatedElement":[{"id":"a236b40b-3240-4162-8309-ba8de4a00b11","eClass":"sysml:Feature","data":{"elementId":"8a6e54a2-dd2a-46c2-840e-a0444dfc17d7","ownedRelationship":[{"id":"d4999cc0-72f8-418c-8a16-8d362577a450","eClass":"sysml:FeatureValue","data":{"elementId":"1371d3c0-f0db-4df2-b39a-86196bffcd6a","ownedRelatedElement":[{"id":"50e3db21-7e60-491c-ac6c-9a7dc9407207","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"4257cf6d-7f15-4fe9-b48e-24a072c6f040","ownedRelationship":[{"id":"87ec1ec4-0515-440b-b35c-8b8581217414","eClass":"sysml:Membership","data":{"elementId":"294b0f69-810d-4be2-bbdc-2022d8aa9794","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"091ee316-159d-400d-94b8-ba0aa5c2f9b5","eClass":"sysml:Membership","data":{"elementId":"1dac782f-da3d-4fe4-9d47-3fa569692bcc","memberElement":"b922024b-5587-4be6-9924-6afa52ce8bf2"}}]}}]}}],"direction":"in"}}]}},{"id":"379e1891-786a-48ee-96a3-d6e3b00cde72","eClass":"sysml:ParameterMembership","data":{"elementId":"ef6e61be-424e-4063-bf2f-a81da5029fcc","ownedRelatedElement":[{"id":"fefc7b1f-cd73-4ef5-95bf-37f12b0749b8","eClass":"sysml:Feature","data":{"elementId":"d080d7d8-b587-4f09-8546-3b7515b73bf7","ownedRelationship":[{"id":"b08c94c0-5fd7-4498-81f8-91cc16df465e","eClass":"sysml:FeatureValue","data":{"elementId":"47f17548-693b-4b52-b6c5-146f93103b88","ownedRelatedElement":[{"id":"f8e0dcc5-6e48-4e37-a14d-37a1026ee01a","eClass":"sysml:LiteralRational","data":{"elementId":"39ac2b8c-4701-4616-8d73-6dc7ffe2c9cd","value":50.0}}]}}],"direction":"in"}}]}}],"operator":">="}}]}}],"direction":"in"}}]}},{"id":"eb8516c8-e8c8-4ee8-939a-55325c8b1cea","eClass":"sysml:ParameterMembership","data":{"elementId":"218a433e-cfa0-4902-9b4e-f0587be3b80e","ownedRelatedElement":[{"id":"c5b2f829-df1b-40ce-83d3-113b3bbfaba5","eClass":"sysml:Feature","data":{"elementId":"4134c6cb-8c93-4d25-af07-c284f7be3969","ownedRelationship":[{"id":"d60596d0-3c29-41a6-b460-898ed9b4c263","eClass":"sysml:FeatureValue","data":{"elementId":"7d1049c4-86cf-4589-b629-8d63970b8583","ownedRelatedElement":[{"id":"eb62764e-be00-4f53-a943-2bb9afe26d4c","eClass":"sysml:OperatorExpression","data":{"elementId":"00efad22-e113-41bc-be71-47de9a1fb9a8","ownedRelationship":[{"id":"64060226-0dc0-4dc1-8a5e-d01c98830213","eClass":"sysml:ParameterMembership","data":{"elementId":"300b058f-b25b-4281-90fe-684eb92606de","ownedRelatedElement":[{"id":"380808e7-4aa1-4f04-8296-8dbe5d1b9fc1","eClass":"sysml:Feature","data":{"elementId":"63ae1974-7814-4c0a-893e-72850334c386","ownedRelationship":[{"id":"23d8c3ac-ca81-45bb-956a-8e8597b49033","eClass":"sysml:FeatureValue","data":{"elementId":"8a290ed0-03f2-495d-bbc6-28f3570feb4b","ownedRelatedElement":[{"id":"4ad5fcc2-dcbe-4254-8e63-f4dc78552ad9","eClass":"sysml:OperatorExpression","data":{"elementId":"ff15a082-0091-4e71-bdf4-8cd81328f2ca","ownedRelationship":[{"id":"3949740d-1e51-4a76-81d9-66066d200c63","eClass":"sysml:ParameterMembership","data":{"elementId":"c63c1f9d-e626-47dc-9d32-59038df3b448","ownedRelatedElement":[{"id":"9a3ac2bf-cc5f-4854-87bc-14a035ad38e5","eClass":"sysml:Feature","data":{"elementId":"47d4f5d4-feb4-404c-9d39-e36cec21db8e","ownedRelationship":[{"id":"9d85853c-5921-4c83-a954-2d022e66f86d","eClass":"sysml:FeatureValue","data":{"elementId":"3f3a18b5-da04-4aa6-831c-984e8a65d47b","ownedRelatedElement":[{"id":"d3f88bd1-b325-4743-920b-e29c5806d7ef","eClass":"sysml:FeatureChainExpression","data":{"elementId":"f0d776b0-fd96-4282-aecd-722d89b96cff","ownedRelationship":[{"id":"89988082-a6b7-408a-99e5-9601ce0a1bf6","eClass":"sysml:ParameterMembership","data":{"elementId":"6ec39eba-a272-4db0-8c70-d16ea7517f86","ownedRelatedElement":[{"id":"51df5f6b-5cb6-48e7-9677-080c823eacca","eClass":"sysml:Feature","data":{"elementId":"53f44fae-071d-4263-9fde-7dc008d14df0","ownedRelationship":[{"id":"e741aa76-c4bc-4afc-95a6-d9d947a279c6","eClass":"sysml:FeatureValue","data":{"elementId":"a938aad2-2fb1-4258-b1c0-730ab660880b","ownedRelatedElement":[{"id":"ef20405c-9d4d-4ee5-bd10-b353bd9d8e1f","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"0e23e1a9-17f0-4ee1-bd4e-9ca406eece66","ownedRelationship":[{"id":"8938cb64-37ff-421a-82c4-3e1fbc43ddd4","eClass":"sysml:Membership","data":{"elementId":"4b50d9b9-0289-4edc-852e-b9037b2ef60f","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"3045651a-778a-43ae-bdb0-b7072ec4bac1","eClass":"sysml:Membership","data":{"elementId":"1a41f919-9831-4a8b-b7ba-5c628414b769","memberElement":"6b9a0d65-eff4-4d98-8b25-d6e24d0486e9"}}]}}]}}],"direction":"in"}}]}},{"id":"fad2ff7a-212e-42e4-9a73-3f8c603d3d37","eClass":"sysml:ParameterMembership","data":{"elementId":"57db7214-0217-449d-8a9b-af78d0334a26","ownedRelatedElement":[{"id":"7c261030-6e18-4072-b4d8-5e700f06f982","eClass":"sysml:Feature","data":{"elementId":"a885a849-350f-41a8-acae-f10b40a21ae8","ownedRelationship":[{"id":"4fc87293-d300-4bdf-b824-c54f9fc9dd91","eClass":"sysml:FeatureValue","data":{"elementId":"1b1e8333-e3e8-4ebc-89b5-1a30a9f54b19","ownedRelatedElement":[{"id":"8d96afc1-c7dd-42ad-a350-57f0b800cc38","eClass":"sysml:LiteralRational","data":{"elementId":"576e66e8-67b6-49c2-957d-738dc65e0309"}}]}}],"direction":"in"}}]}}],"operator":"!="}}]}}],"direction":"in"}}]}},{"id":"03c4fde9-59c7-4499-b22c-f76128218acc","eClass":"sysml:ParameterMembership","data":{"elementId":"8b82cb63-e3d2-410a-86d5-053d9c4de34e","ownedRelatedElement":[{"id":"7949920d-fef9-4ada-a1fd-6146f740a9af","eClass":"sysml:Feature","data":{"elementId":"13999012-8669-458a-9a12-09a4344c25c5","ownedRelationship":[{"id":"7f0c0cbc-d241-42e4-9631-63195ec2387e","eClass":"sysml:FeatureValue","data":{"elementId":"4ae968bd-9835-490f-b122-70579a109558","ownedRelatedElement":[{"id":"4ca5a50e-d116-4b29-9e5c-bff45c6685d9","eClass":"sysml:OperatorExpression","data":{"elementId":"097d302b-bd39-4fdf-b37d-bfaf274d684a","ownedRelationship":[{"id":"c1b9246d-6c33-4efa-8349-63eca55ed258","eClass":"sysml:ParameterMembership","data":{"elementId":"acbda919-a449-4e50-8769-21c05c333f6e","ownedRelatedElement":[{"id":"7b99f3f9-9a46-4dc1-b31b-15b4f243e8e2","eClass":"sysml:Feature","data":{"elementId":"72c64d09-668a-4881-94f2-a02ee97e7f08","ownedRelationship":[{"id":"1ccd4617-8a24-40c1-b1bf-e14c57948d68","eClass":"sysml:FeatureValue","data":{"elementId":"df287639-e735-491a-8fe5-77e377244ea0","ownedRelatedElement":[{"id":"3b7a7f00-42b4-4962-8249-201ea3546292","eClass":"sysml:FeatureChainExpression","data":{"elementId":"39c623a8-db65-483c-b49d-6476f1eb02a7","ownedRelationship":[{"id":"c4b1bdfe-008a-42e2-a0da-560ef61c0657","eClass":"sysml:ParameterMembership","data":{"elementId":"dd1c5acd-02d0-40d5-a509-f934c915227d","ownedRelatedElement":[{"id":"f952d5b2-527e-4487-ad14-a501cbb4ec32","eClass":"sysml:Feature","data":{"elementId":"2302b015-7719-4042-9929-e4ad7cf7b1eb","ownedRelationship":[{"id":"ce4564b8-6fe7-49fc-a146-5d14b3c7405e","eClass":"sysml:FeatureValue","data":{"elementId":"6b6dae15-eda9-4734-8313-71897cfb4fe1","ownedRelatedElement":[{"id":"cbb045fe-e306-4bf8-84ed-e105822603f7","eClass":"sysml:FeatureReferenceExpression","data":{"elementId":"dac96cd8-1b64-4b8f-86d2-f9c162cb33a2","ownedRelationship":[{"id":"1fcde9a2-93af-4f46-b5af-0e6b2c94f94e","eClass":"sysml:Membership","data":{"elementId":"ec45938e-93b4-4039-8f0c-8fb5fae4bea0","memberElement":"33466a30-d081-4d0d-a3dc-142c59b82000"}}]}}]}}],"direction":"in"}}]}},{"id":"c3ae80a8-eeb0-4fd4-8d1a-36b18bf83520","eClass":"sysml:Membership","data":{"elementId":"b81cd454-88de-46fa-b993-db22a7a5d0bb","memberElement":"4d2f8465-d748-4b68-a5a8-d61c03031bd3"}}]}}]}}],"direction":"in"}}]}},{"id":"11ebb0eb-72cc-46a0-98f6-c135660b2e82","eClass":"sysml:ParameterMembership","data":{"elementId":"db89e0f5-6177-4b68-8850-44f7e32dd602","ownedRelatedElement":[{"id":"479d4b8c-c79b-42d3-805a-afc1dfa21852","eClass":"sysml:Feature","data":{"elementId":"83978f47-55dd-4399-a8b4-e84a7c03c13d","ownedRelationship":[{"id":"20aa93bd-a3fc-4985-b34a-c7d0cb4f8a98","eClass":"sysml:FeatureValue","data":{"elementId":"5ab031d1-3718-46a1-ae8c-c1eb2f226c3d","ownedRelatedElement":[{"id":"0f874cca-dc06-4430-89b8-a00dee51eaee","eClass":"sysml:LiteralInteger","data":{"elementId":"88c30f81-c3ce-4804-9142-c0b33f51dcd3"}}]}}],"direction":"in"}}]}}],"operator":"=="}}]}}],"direction":"in"}}]}}],"operator":"|"}}]}}],"direction":"in"}}]}}],"operator":"&"}}]}}],"isComposite":true}}],"kind":"requirement"}}]}}]}}]}}]}}]}}]}', '2026-05-20 16:21:07.743843+00', '2026-05-20 16:21:07.743843+00', false); -- diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/ASTTransformer.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/ASTTransformer.java index 38c897125..d40f5d17d 100644 --- a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/ASTTransformer.java +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/ASTTransformer.java @@ -19,6 +19,8 @@ import java.util.List; import java.util.ListIterator; import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; @@ -28,6 +30,7 @@ import org.eclipse.sirius.components.representations.Message; import org.eclipse.syson.services.DeleteService; import org.eclipse.syson.sysml.helper.EMFUtils; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; import org.eclipse.syson.sysml.parser.AstTreeParser; import org.eclipse.syson.sysml.parser.ContainmentReferenceHandler; import org.eclipse.syson.sysml.parser.EAttributeHandler; @@ -57,6 +60,8 @@ public class ASTTransformer { private final NonContainmentReferenceHandler nonContainmentReferenceHandler; + private final MetamodelQueryElementService metamodelQueryElementService; + public ASTTransformer() { this.messageReporter = new MessageReporter(); this.nonContainmentReferenceHandler = new NonContainmentReferenceHandler(this.messageReporter); @@ -64,6 +69,7 @@ public ASTTransformer() { var proxyResolver = new ProxyResolver(this.messageReporter); var astObjectParser = new EAttributeHandler(this.messageReporter); this.astTreeParser = new AstTreeParser(astContainmentReferenceParser, this.nonContainmentReferenceHandler, proxyResolver, astObjectParser, this.messageReporter); + this.metamodelQueryElementService = new MetamodelQueryElementService(); } public Resource convertResource(final InputStream input, final ResourceSet resourceSet) { @@ -89,43 +95,59 @@ public Resource convertResource(final InputStream input, final ResourceSet resou * * @param input * the textual representation - * @param resourceSet - * the current {@link ResourceSet} * @param parentElement - * the parent element in which created element will be added. + * the parent element in which created element will be added. May be null if we only validate. + * @return the list of the created elements + */ + public List convertToElements(InputStream input, Element parentElement) { + return this.convertToElements(input, parentElement, null, (messages) -> Boolean.FALSE); + } + + /** + * Convert the given SysML text into Elements and add them into the given parent. + * + * @param input + * the textual representation + * @param parentElement + * the parent element in which created element will be added. May be null if we only validate. + * @param contentSelector + * a function to select the SysML Elements of actual interest from the result of syside's parsing. + * @param shouldRevertPredicate + * predicate invoked after the operation is done to determine, given the impact (as reported by the + * messages), if it should be reverted. * @return the list of the created elements */ - public List convertToElements(final InputStream input, final ResourceSet resourceSet, Element parentElement) { + public List convertToElements(InputStream input, Element parentElement, Function, List> contentSelector, Predicate> shouldRevertPredicate) { List result = List.of(); if (input != null) { final JsonNode astJson = this.readAst(input); if (astJson != null) { this.logger.info("Create the Root eObject containment structure"); - result = this.extractContent(this.astTreeParser.parseAst(astJson)); + List parsedAst = this.astTreeParser.parseAst(astJson); + var contents = this.getNamespaceContent(parsedAst); + if (contentSelector != null) { + result = contentSelector.apply(contents); + } else { + result = contents; + } this.logger.info("File Parsed"); + List undo = new ArrayList<>(); for (Element root : result) { - this.addInParent(parentElement, root); + undo.add(this.addInParent(parentElement, root)); } this.logger.info("Elements added in parent"); this.fixAndResolve(result); + + if (shouldRevertPredicate.test(this.messageReporter.getReportedMessages())) { + undo.reversed().forEach(Runnable::run); + } } } return result; } - private void fixAndResolve(List result) { - this.preResolvingFixingPhase(result); - - List proxiedReferences = this.nonContainmentReferenceHandler.getProxiesToResolve(); - this.logger.info("{} references to resolve.", proxiedReferences.size()); - this.astTreeParser.resolveAllReference(proxiedReferences); - this.logger.info("End of references resolving"); - - this.postResolvingFixingPhase(result); - } - - private List extractContent(List roots) { + private List getNamespaceContent(List roots) { return roots.stream().filter(Namespace.class::isInstance) .map(Namespace.class::cast) .flatMap(ns -> ns.getOwnedRelationship().stream()) @@ -143,20 +165,57 @@ private List getChildren(Relationship relationship) { return children; } - private void addInParent(Element parent, Element child) { + private void fixAndResolve(List result) { + this.preResolvingFixingPhase(result); + + List proxiedReferences = this.nonContainmentReferenceHandler.getProxiesToResolve(); + this.logger.info("{} references to resolve.", proxiedReferences.size()); + this.astTreeParser.resolveAllReference(proxiedReferences); + this.logger.info("End of references resolving"); + + this.postResolvingFixingPhase(result); + } + + /** + * Add a child element inside a parent, using the appropriate relationship. + * + * @param parent + * the parent element. + * @param child + * the child to add. + * @return a Runnable that can be executed to undo the addition. + */ + private Runnable addInParent(Element parent, Element child) { + Runnable undo = () -> { + // No-op + }; if (child instanceof Import imp) { parent.getOwnedRelationship().add(imp); + undo = () -> parent.getOwnedRelationship().remove(imp); + } else if (child instanceof Expression expr) { + var compatibleOwnerships = this.metamodelQueryElementService.getCompatibleExpressionOwnerships(parent); + if (!compatibleOwnerships.isEmpty()) { + var selectedOwnership = compatibleOwnerships.get(0); + selectedOwnership.getOwnedRelatedElement().add(expr); + parent.getOwnedRelationship().add(selectedOwnership); + selectedOwnership.getOwnedRelatedElement().add(child); + undo = () -> parent.getOwnedRelationship().remove(selectedOwnership); + } } else if (child instanceof Feature && parent instanceof Type) { Membership membership = SysmlFactory.eINSTANCE.createFeatureMembership(); - parent.getOwnedRelationship().add(membership); membership.getOwnedRelatedElement().add(child); + parent.getOwnedRelationship().add(membership); + undo = () -> parent.getOwnedRelationship().remove(membership); } else if (parent instanceof Package || SysmlPackage.eINSTANCE.getNamespace().equals(parent.eClass())) { Membership membership = SysmlFactory.eINSTANCE.createOwningMembership(); membership.getOwnedRelatedElement().add(child); parent.getOwnedRelationship().add(membership); + undo = () -> parent.getOwnedRelationship().remove(membership); } else if (child instanceof Relationship rel) { parent.getOwnedRelationship().add(rel); + undo = () -> parent.getOwnedRelationship().remove(rel); } + return undo; } private void postResolvingFixingPhase(List rootSysmlObjects) { @@ -169,11 +228,11 @@ private void postResolvingFixingPhase(List rootSysmlObjects) } /** - * The current implementation of the parser does not force the memberFeature of EndFeatureMembership to have "isEnd = true" like stated in the SysML specification see "8.3.3.3.3 - * EndFeatureMembership". + * The current implementation of the parser does not force the memberFeature of EndFeatureMembership to have "isEnd + * = true" like stated in the SysML specification see "8.3.3.3.3 EndFeatureMembership". * * @param root - * the root of the imported object + * the root of the imported object */ private void fixEndFeatureMembership(EObject root) { EMFUtils.allContainedObjectOfType(root, EndFeatureMembership.class) diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationCreateExpressionDataFetcher.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationCreateExpressionDataFetcher.java new file mode 100644 index 000000000..b2f6e9a00 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationCreateExpressionDataFetcher.java @@ -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.sysml.datafetchers; + +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.sysml.dto.CreateExpressionInput; + +import graphql.schema.DataFetchingEnvironment; +import tools.jackson.databind.ObjectMapper; + +/** + * Data fetcher for the {@code EditingContext#createExpression} mutation. + * + * @author pcdavid + */ +@MutationDataFetcher(type = "Mutation", field = "createExpression") +public class MutationCreateExpressionDataFetcher implements IDataFetcherWithFieldCoordinates> { + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationCreateExpressionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, CreateExpressionInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationEditExpressionDataFetcher.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationEditExpressionDataFetcher.java new file mode 100644 index 000000000..942b8441e --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/datafetchers/MutationEditExpressionDataFetcher.java @@ -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.sysml.datafetchers; + +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.sysml.dto.EditExpressionInput; + +import graphql.schema.DataFetchingEnvironment; +import tools.jackson.databind.ObjectMapper; + +/** + * Data fetcher for the {@code EditingContext#editExpression} mutation. + * + * @author pcdavid + */ +@MutationDataFetcher(type = "Mutation", field = "editExpression") +public class MutationEditExpressionDataFetcher implements IDataFetcherWithFieldCoordinates> { + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationEditExpressionDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, EditExpressionInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionInput.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionInput.java new file mode 100644 index 000000000..7cdddbc3c --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionInput.java @@ -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.sysml.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IInput; + +/** + * The input object of the createExpression operation. + * + * @author pcdavid + */ +public record CreateExpressionInput(UUID id, String editingContextId, String parentElementId, String expressionText) implements IInput { +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionSuccessPayload.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionSuccessPayload.java new file mode 100644 index 000000000..e319cde43 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/CreateExpressionSuccessPayload.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.sysml.dto; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.representations.Message; + +/** + * The result returned by the {@code createExpression} mutation on success. + * + * @author pcdavid + */ +public record CreateExpressionSuccessPayload(UUID id, String newExpressionId, List messages) implements IPayload { + public CreateExpressionSuccessPayload { + Objects.requireNonNull(id); + Objects.requireNonNull(newExpressionId); + Objects.requireNonNull(messages); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionInput.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionInput.java new file mode 100644 index 000000000..dac6921c0 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionInput.java @@ -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.sysml.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IInput; + +/** + * The input object of the {@code editExpression} mutation. + * + * @author pcdavid + */ +public record EditExpressionInput(UUID id, String editingContextId, String expressionElementId, String newExpressionText) implements IInput { +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionSuccessPayload.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionSuccessPayload.java new file mode 100644 index 000000000..068763069 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/EditExpressionSuccessPayload.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.sysml.dto; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.representations.Message; + +/** + * The result returned by the {@code editExpression} mutation on success. + * + * @author pcdavid + */ +public record EditExpressionSuccessPayload(UUID id, String newExpressionId, List messages) implements IPayload { + public EditExpressionSuccessPayload { + Objects.requireNonNull(id); + Objects.requireNonNull(newExpressionId); + Objects.requireNonNull(messages); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/CreateExpressionEventHandler.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/CreateExpressionEventHandler.java new file mode 100644 index 000000000..15ce52584 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/CreateExpressionEventHandler.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.sysml.services; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventHandler; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.messages.ICollaborativeMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IIdentityService; +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.dto.CreateExpressionInput; +import org.eclipse.syson.sysml.dto.CreateExpressionSuccessPayload; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; +import org.eclipse.syson.sysml.services.api.ISysMLExpressionEditor; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks.Many; +import reactor.core.publisher.Sinks.One; + +/** + * Handler used to execute the {@code createExpression} operation. + * + * @author pcdavid + */ +@Service +public class CreateExpressionEventHandler implements IEditingContextEventHandler { + + private final IObjectSearchService objectSearchService; + + private final IIdentityService identityService; + + private final ISysMLExpressionEditor expressionEditor; + + private final MetamodelQueryElementService metamodelQueryElementService; + + private final ICollaborativeMessageService messageService; + + private final Counter counter; + + public CreateExpressionEventHandler(IObjectSearchService objectSearchService, IIdentityService identityService, ISysMLExpressionEditor expressionEditor, + ICollaborativeMessageService messageService, MeterRegistry meterRegistry) { + this.objectSearchService = Objects.requireNonNull(objectSearchService); + this.identityService = Objects.requireNonNull(identityService); + this.expressionEditor = Objects.requireNonNull(expressionEditor); + this.metamodelQueryElementService = new MetamodelQueryElementService(); + this.messageService = Objects.requireNonNull(messageService); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IEditingContext editingContext, IInput input) { + return editingContext instanceof IEMFEditingContext && input instanceof CreateExpressionInput; + } + + @Override + public void handle(One payloadSink, Many changeDescriptionSink, IEditingContext editingContext, IInput input) { + this.counter.increment(); + IPayload payload; + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, editingContext.getId(), input); + + if (input instanceof CreateExpressionInput createExpressionInput && editingContext instanceof IEMFEditingContext emfEditingContext) { + Optional optionalParentElement = this.objectSearchService.getObject(editingContext, createExpressionInput.parentElementId()) + .filter(Element.class::isInstance) + .map(Element.class::cast); + if (optionalParentElement.isPresent()) { + if (this.metamodelQueryElementService.hasSingleExpressionDefinition(optionalParentElement.get())) { + payload = new ErrorPayload(input.id(), "The parent element already has an expression"); + } else { + var result = this.expressionEditor.createExpression(emfEditingContext, optionalParentElement.get(), createExpressionInput.expressionText()); + if (result.createdExpression() != null) { + var createdExpression = result.createdExpression(); + var createdExpressionId = this.identityService.getId(createdExpression); + changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input); + payload = new CreateExpressionSuccessPayload(input.id(), createdExpressionId, result.messages()); + } else { + payload = new ErrorPayload(input.id(), result.messages()); + } + } + } else { + payload = new ErrorPayload(input.id(), this.messageService.notFound()); + } + } else { + payload = new ErrorPayload(input.id(), this.messageService.invalidInput(CreateExpressionInput.class.getName(), input.getClass().getName())); + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/EditExpressionEventHandler.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/EditExpressionEventHandler.java new file mode 100644 index 000000000..02d6077ab --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/EditExpressionEventHandler.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * 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.sysml.services; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventHandler; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.messages.ICollaborativeMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IIdentityService; +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; +import org.eclipse.syson.sysml.dto.EditExpressionInput; +import org.eclipse.syson.sysml.dto.EditExpressionSuccessPayload; +import org.eclipse.syson.sysml.services.api.ISysMLExpressionEditor; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks; + +/** + * Event handler for the {@code editExpression} mutation. + * + * @author pcdavid + */ +@Service +public class EditExpressionEventHandler implements IEditingContextEventHandler { + + private final IObjectSearchService objectSearchService; + + private final IIdentityService identityService; + + private final ICollaborativeMessageService messageService; + + private final ISysMLExpressionEditor expressionEditor; + + private final Counter counter; + + public EditExpressionEventHandler(IObjectSearchService objectSearchService, IIdentityService identityService, ICollaborativeMessageService messageService, ISysMLExpressionEditor expressionEditor, + MeterRegistry meterRegistry) { + this.objectSearchService = Objects.requireNonNull(objectSearchService); + this.identityService = Objects.requireNonNull(identityService); + this.messageService = Objects.requireNonNull(messageService); + this.expressionEditor = Objects.requireNonNull(expressionEditor); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IEditingContext editingContext, IInput input) { + return editingContext instanceof IEMFEditingContext && input instanceof EditExpressionInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, IInput input) { + this.counter.increment(); + IPayload payload; + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, editingContext.getId(), input); + + if (input instanceof EditExpressionInput editExpressionInput && editingContext instanceof IEMFEditingContext emfEditingContext) { + Optional optionalExpression = this.objectSearchService.getObject(editingContext, editExpressionInput.expressionElementId()) + .filter(Expression.class::isInstance) + .map(Expression.class::cast); + Optional optionalParent = Optional.empty(); + if (optionalExpression.isPresent()) { + optionalParent = Optional.ofNullable(optionalExpression.get().getOwner()); + } + + if (optionalParent.isPresent() && optionalExpression.isPresent()) { + var result = this.expressionEditor.editExpression(emfEditingContext, optionalParent.get(), optionalExpression.get(), editExpressionInput.newExpressionText()); + if (result.createdExpression() != null) { + var newExpression = result.createdExpression(); + var newExpressionId = this.identityService.getId(newExpression); + + changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input); + payload = new EditExpressionSuccessPayload(input.id(), newExpressionId, result.messages()); + } else { + payload = new ErrorPayload(input.id(), result.messages()); + } + } else { + payload = new ErrorPayload(input.id(), this.messageService.notFound()); + } + } else { + payload = new ErrorPayload(input.id(), this.messageService.invalidInput(EditExpressionInput.class.getName(), input.getClass().getName())); + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/InsertTextualSysMLv2EventHandler.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/InsertTextualSysMLv2EventHandler.java similarity index 60% rename from backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/InsertTextualSysMLv2EventHandler.java rename to backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/InsertTextualSysMLv2EventHandler.java index 30b2ad919..e6d02fdcd 100644 --- a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/dto/InsertTextualSysMLv2EventHandler.java +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/InsertTextualSysMLv2EventHandler.java @@ -10,12 +10,12 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ -package org.eclipse.syson.sysml.dto; +package org.eclipse.syson.sysml.services; -import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; import org.eclipse.sirius.components.collaborative.api.ChangeDescription; import org.eclipse.sirius.components.collaborative.api.ChangeKind; @@ -31,10 +31,9 @@ import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; import org.eclipse.sirius.components.representations.Message; import org.eclipse.sirius.components.representations.MessageLevel; -import org.eclipse.syson.sysml.ASTTransformer; import org.eclipse.syson.sysml.Element; -import org.eclipse.syson.sysml.SysmlToAst; -import org.eclipse.syson.sysml.textual.utils.Status; +import org.eclipse.syson.sysml.dto.InsertTextualSysMLv2Input; +import org.eclipse.syson.sysml.services.api.ISysMLTextImporter; import org.springframework.stereotype.Service; import io.micrometer.core.instrument.Counter; @@ -52,17 +51,16 @@ public class InsertTextualSysMLv2EventHandler implements IEditingContextEventHan private final IObjectSearchService objectSearchService; - private final ICollaborativeMessageService messageService; + private final ISysMLTextImporter sysmlTextImporter; - private final SysmlToAst sysmlToAst; + private final ICollaborativeMessageService messageService; private final Counter counter; - public InsertTextualSysMLv2EventHandler(IObjectSearchService objectSearchService, ICollaborativeMessageService messageService, - SysmlToAst sysmlToAst, MeterRegistry meterRegistry) { + public InsertTextualSysMLv2EventHandler(IObjectSearchService objectSearchService, ISysMLTextImporter sysmlTextImporter, ICollaborativeMessageService messageService, MeterRegistry meterRegistry) { this.objectSearchService = Objects.requireNonNull(objectSearchService); + this.sysmlTextImporter = Objects.requireNonNull(sysmlTextImporter); this.messageService = Objects.requireNonNull(messageService); - this.sysmlToAst = Objects.requireNonNull(sysmlToAst); this.counter = Counter.builder(Monitoring.EVENT_HANDLER) .tag(Monitoring.NAME, this.getClass().getSimpleName()) .register(meterRegistry); @@ -85,12 +83,12 @@ public void handle(One payloadSink, Many changeDesc if (input instanceof InsertTextualSysMLv2Input insertTextualInput && editingContext instanceof IEMFEditingContext emfEditingContext) { messages = new ArrayList<>(); - var parentObjectId = insertTextualInput.objectId(); - var parentElement = this.getParentElement(parentObjectId, emfEditingContext); - if (parentElement != null) { - var transformer = new ASTTransformer(); - var newObjects = this.convert(insertTextualInput, emfEditingContext, transformer, parentElement, messages); - messages.addAll(transformer.getTransformationMessages()); + var optionalParentElement = this.resolveElement(emfEditingContext, insertTextualInput.objectId()); + if (optionalParentElement.isPresent()) { + var parent = optionalParentElement.get(); + var textualContent = insertTextualInput.textualContent(); + + var newObjects = this.sysmlTextImporter.importSysMLText(emfEditingContext, parent, textualContent, messages); if (!newObjects.isEmpty()) { payload = new SuccessPayload(input.id(), messages); changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input); @@ -108,44 +106,10 @@ public void handle(One payloadSink, Many changeDesc changeDescriptionSink.tryEmitNext(changeDescription); } - private Element getParentElement(String parentObjectId, IEMFEditingContext emfEditingContext) { - var parentObject = this.objectSearchService.getObject(emfEditingContext, parentObjectId); - if (parentObject.isPresent()) { - var object = parentObject.get(); - if (object instanceof Element parentElement) { - return parentElement; - } - } - return null; - } - - private List convert(InsertTextualSysMLv2Input insertTextualInput, IEMFEditingContext emfEditingContext, ASTTransformer transformer, Element parentElement, List messages) { - var textualContent = insertTextualInput.textualContent(); - var resourceSet = emfEditingContext.getDomain().getResourceSet(); - var inputStream = new ByteArrayInputStream(textualContent.getBytes()); - var astParsingResult = this.sysmlToAst.convert(inputStream, ".sysml"); - messages.addAll(astParsingResult.reports().stream() - .map(this::toMessage) - .filter(Objects::nonNull) - .toList()); - if (astParsingResult.ast().isPresent()) { - return transformer.convertToElements(astParsingResult.ast().get(), resourceSet, parentElement); - } else { - return List.of(); - } + private Optional resolveElement(IEMFEditingContext emfEditingContext, String objectId) { + return this.objectSearchService.getObject(emfEditingContext, objectId) + .filter(Element.class::isInstance) + .map(Element.class::cast); } - private Message toMessage(Status status) { - MessageLevel msgLevel = switch (status.severity()) { - case INFO -> MessageLevel.INFO; - case WARNING -> MessageLevel.WARNING; - case ERROR -> MessageLevel.ERROR; - default -> null; - }; - if (msgLevel != null) { - return new Message(status.message(), msgLevel); - } else { - return null; - } - } } diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideExpressionEditor.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideExpressionEditor.java new file mode 100644 index 000000000..1989550b2 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideExpressionEditor.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * 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.sysml.services; + +import java.io.ByteArrayInputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.components.representations.Message; +import org.eclipse.sirius.components.representations.MessageLevel; +import org.eclipse.syson.sysml.ASTTransformer; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.Function; +import org.eclipse.syson.sysml.Relationship; +import org.eclipse.syson.sysml.StateUsage; +import org.eclipse.syson.sysml.SysmlToAst; +import org.eclipse.syson.sysml.TransitionFeatureKind; +import org.eclipse.syson.sysml.TransitionFeatureMembership; +import org.eclipse.syson.sysml.TransitionUsage; +import org.eclipse.syson.sysml.services.api.ExpressionCreationResult; +import org.eclipse.syson.sysml.services.api.ISysMLExpressionEditor; +import org.eclipse.syson.sysml.textual.utils.Status; +import org.springframework.stereotype.Service; + +/** + * syside-based implementation of {@link ISysMLExpressionEditor}. + * + * @author pcdavid + */ +@Service +public class SysideExpressionEditor implements ISysMLExpressionEditor { + + private final SysmlToAst sysmlToAst; + + public SysideExpressionEditor(SysmlToAst sysmlToAst) { + this.sysmlToAst = Objects.requireNonNull(sysmlToAst); + } + + @Override + public ExpressionCreationResult createExpression(IEMFEditingContext emfEditingContext, Element parentElement, String expressionText) { + return this.createOrEditExpression(emfEditingContext, parentElement, Optional.empty(), expressionText); + } + + @Override + public ExpressionCreationResult editExpression(IEMFEditingContext emfEditingContext, Element parentElement, Expression expression, String expressionText) { + return this.createOrEditExpression(emfEditingContext, parentElement, Optional.of(expression), expressionText); + } + + private ExpressionCreationResult createOrEditExpression(IEMFEditingContext emfEditingContext, Element parentElement, Optional expressionToReplace, String expressionText) { + List newObjects = List.of(); + List messages = new ArrayList<>(); + + // Needed to force the syside parser to treat the input text as an Expression. + var wrappedText = this.wrapPlainExpression(parentElement, expressionText); + + // Phase 1: parse the raw text into a JSON AST using syside-cli + var inputStream = new ByteArrayInputStream(wrappedText.getBytes()); + var astParsingResult = this.sysmlToAst.convert(inputStream, ".sysml"); + messages.addAll(this.toMessages(astParsingResult.reports())); + + // Phase 2: "parse" the resulting JSON AST into actual SySMLv2 Elements and integrate them into + // parentElement + if (astParsingResult.ast().isPresent()) { + var transformer = new ASTTransformer(); + newObjects = transformer.convertToElements(astParsingResult.ast().get(), parentElement, this::unwrap, this::containsErrors); + messages.addAll(transformer.getTransformationMessages()); + } + boolean success = !this.containsErrors(messages); + var optionalResult = this.getNewExpression(newObjects); + + if (success && optionalResult.isPresent()) { + if (expressionToReplace.isPresent()) { + this.replace(expressionToReplace.get(), optionalResult.get()); + } + return new ExpressionCreationResult(optionalResult.get(), messages); + } else { + return new ExpressionCreationResult(null, messages); + } + } + + private boolean containsErrors(List messages) { + return messages.stream().anyMatch(message -> message.level().equals(MessageLevel.WARNING) || message.level().equals(MessageLevel.ERROR)); + } + + private Optional getNewExpression(List newObjects) { + if (!newObjects.isEmpty() && newObjects.get(0) instanceof Relationship relationship && !relationship.getOwnedRelatedElement().isEmpty() + && relationship.getOwnedRelatedElement().get(0) instanceof Expression newExpression) { + return Optional.of(newExpression); + } else { + return Optional.empty(); + } + } + + private void replace(Expression expression, Expression newExpression) { + if (newExpression.getOwningRelationship() != null) { + EcoreUtil.remove(newExpression.getOwningRelationship()); + } + if (expression.getOwningRelationship() != null) { + EList relatedElements = expression.getOwningRelationship().getOwnedRelatedElement(); + int index = relatedElements.indexOf(expression); + relatedElements.add(index, newExpression); + relatedElements.remove(expression); + } + } + + /** + * Wraps the plain expression entered by the user into a top-level construct of the appropriate kind to force the + * syside parser to actually interpret it as an Expression. + * + * @param parentElement + * @param plainExpression + * @return + */ + private String wrapPlainExpression(Element parentElement, String plainExpression) { + UUID uniqueName = UUID.randomUUID(); + String template = ""; + if (parentElement instanceof TransitionUsage) { + // Will produce a more complex structure inside which we'll find the actual + // TransitionFeatureMembership[kind=GUARD] -> + // Expression. See extractGuardExpression(). + template = """ + state <'%s'> { + entry action init; + state off; + transition first init if %s then off; + } + """; + } else if (parentElement instanceof Function || parentElement instanceof Expression) { + // Will produce ConstraintDefition -> ResultExpressionMembership -> Expression + template = "constraint def <'%s'> { %s }"; + } else if (parentElement instanceof Feature) { + // Will produce AttributeUsage -> FeatureValue -> Expression + template = "attribute <'%s'> = %s;"; + } + return String.format(template, uniqueName, plainExpression); + } + + /** + * Extracts the expression and its parent relationship once they have been parsed and linked. This is the reverse of + * {@link #wrapPlainExpression(Element, String)}. + * + * @param roots + * @return + */ + private List unwrap(List roots) { + Element result = null; + var parentElement = roots.stream().findFirst().orElse(null); + if (parentElement instanceof StateUsage wrappingState) { + result = this.extractGuardExpression(wrappingState); + } else if (parentElement instanceof Function || parentElement instanceof Expression) { + result = parentElement.getOwnedRelationship().stream().map(Element.class::cast).findFirst().orElse(null); + } else if (parentElement instanceof Feature) { + result = parentElement.getOwnedRelationship().stream().map(Element.class::cast).findFirst().orElse(null); + } + + return Optional.ofNullable(result).stream().toList(); + } + + private Element extractGuardExpression(StateUsage wrappingState) { + Element result; + result = wrappingState.getOwnedRelationship().get(2) + .getOwnedRelatedElement().get(0) + .getOwnedRelationship().stream() + .filter(TransitionFeatureMembership.class::isInstance) + .map(TransitionFeatureMembership.class::cast) + .filter(tfm -> tfm.getKind() == TransitionFeatureKind.GUARD) + .findFirst() + .orElse(null); + return result; + } + + private List toMessages(List reports) { + return reports.stream().map((Status status) -> { + return switch (status.severity()) { + case INFO -> new Message(status.message(), MessageLevel.INFO); + case WARNING -> new Message(status.message(), MessageLevel.WARNING); + case ERROR -> new Message(status.message(), MessageLevel.ERROR); + default -> null; + }; + }).filter(Objects::nonNull).toList(); + } + +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideSysMLTextImporter.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideSysMLTextImporter.java new file mode 100644 index 000000000..166f1c178 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/SysideSysMLTextImporter.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.sysml.services; + +import java.io.ByteArrayInputStream; +import java.util.List; +import java.util.Objects; + +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.components.representations.Message; +import org.eclipse.sirius.components.representations.MessageLevel; +import org.eclipse.syson.sysml.ASTTransformer; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.SysmlToAst; +import org.eclipse.syson.sysml.services.api.ISysMLTextImporter; +import org.eclipse.syson.sysml.textual.utils.Status; +import org.springframework.stereotype.Service; + +/** + * syside-based implementation of {@code ISysMLTextImporter}. + * + * @author pcdavid + */ +@Service +public class SysideSysMLTextImporter implements ISysMLTextImporter { + private final SysmlToAst sysmlToAst; + + public SysideSysMLTextImporter(SysmlToAst sysmlToAst) { + this.sysmlToAst = Objects.requireNonNull(sysmlToAst); + } + + @Override + public List importSysMLText(IEMFEditingContext emfEditingContext, Element parentElement, String textualContent, List messages) { + List newObjects = List.of(); + + // Phase 1: parse the raw text into a JSON AST using syside-cli + var inputStream = new ByteArrayInputStream(textualContent.getBytes()); + var astParsingResult = this.sysmlToAst.convert(inputStream, ".sysml"); + messages.addAll(this.toMessages(astParsingResult.reports())); + + // Phase 2: convert the resulting JSON AST into actual SySMLv2 Elements and integrate them into + // parentElement. + if (astParsingResult.ast().isPresent()) { + var transformer = new ASTTransformer(); + newObjects = transformer.convertToElements(astParsingResult.ast().get(), parentElement); + messages.addAll(transformer.getTransformationMessages()); + } + + return newObjects; + } + + private List toMessages(List reports) { + return reports.stream().map((Status status) -> { + return switch (status.severity()) { + case INFO -> new Message(status.message(), MessageLevel.INFO); + case WARNING -> new Message(status.message(), MessageLevel.WARNING); + case ERROR -> new Message(status.message(), MessageLevel.ERROR); + default -> null; + }; + }).filter(Objects::nonNull).toList(); + } +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ExpressionCreationResult.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ExpressionCreationResult.java new file mode 100644 index 000000000..460e3237d --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ExpressionCreationResult.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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.sysml.services.api; + +import java.util.List; + +import org.eclipse.sirius.components.representations.Message; +import org.eclipse.syson.sysml.Expression; + +/** + * The result of creating a new expression from text. {@code createdExpression} may be null to indicate the + * expression could not be created, in which case {@cope messages} will contain the reason(s) for the failure. + * + * @author pcdavid + */ +public record ExpressionCreationResult(Expression createdExpression, List messages) { +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLExpressionEditor.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLExpressionEditor.java new file mode 100644 index 000000000..e7755092c --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLExpressionEditor.java @@ -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.sysml.services.api; + +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; + +/** + * Use to create of edit a SySMLv2 {@link Expression} in a given context from a given text fragment. + * + * @author pcdavid + */ +public interface ISysMLExpressionEditor { + ExpressionCreationResult createExpression(IEMFEditingContext emfEditingContext, Element parentElement, String expressionText); + + // "Editing" an expression actually means creating a new one to replace the previous one. + ExpressionCreationResult editExpression(IEMFEditingContext emfEditingContext, Element parentElement, Expression expression, String expressionText); +} diff --git a/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLTextImporter.java b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLTextImporter.java new file mode 100644 index 000000000..d75a1d231 --- /dev/null +++ b/backend/application/syson-sysml-import/src/main/java/org/eclipse/syson/sysml/services/api/ISysMLTextImporter.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * 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.sysml.services.api; + +import java.util.List; + +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.components.representations.Message; +import org.eclipse.syson.sysml.Element; + +/** + * Use to import a SySMLv2 text fragment as new objects inside an existing element. + * + * @author pcdavid + */ +public interface ISysMLTextImporter { + List importSysMLText(IEMFEditingContext emfEditingContext, Element parentElement, String textualContent, List messages); +} diff --git a/backend/application/syson-sysml-import/src/main/resources/schema/syson-import.graphqls b/backend/application/syson-sysml-import/src/main/resources/schema/syson-import.graphqls index b49525150..a2df45eca 100644 --- a/backend/application/syson-sysml-import/src/main/resources/schema/syson-import.graphqls +++ b/backend/application/syson-sysml-import/src/main/resources/schema/syson-import.graphqls @@ -1,4 +1,3 @@ - extend type Mutation { insertTextualSysMLv2(input: InsertTextualSysMLv2Input!): InsertTextualSysMLv2Payload! } @@ -11,3 +10,38 @@ input InsertTextualSysMLv2Input { } union InsertTextualSysMLv2Payload = ErrorPayload | SuccessPayload + +extend type Mutation { + createExpression(input: CreateExpressionInput!): CreateExpressionPayload! + editExpression(input: EditExpressionInput!): EditExpressionPayload! +} + +input CreateExpressionInput { + id: ID! + editingContextId: ID! + parentElementId: ID! + expressionText: String! +} + +union CreateExpressionPayload = ErrorPayload | CreateExpressionSuccessPayload + +type CreateExpressionSuccessPayload { + id: ID! + newExpressionId: ID! + messages: [Message]! +} + +input EditExpressionInput { + id: ID! + editingContextId: ID! + expressionElementId: ID! + newExpressionText: String! +} + +union EditExpressionPayload = ErrorPayload | EditExpressionSuccessPayload + +type EditExpressionSuccessPayload { + id: ID! + newExpressionId: ID! + messages: [Message]! +} \ No newline at end of file diff --git a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ResultExpressionMembershipImpl.java b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ResultExpressionMembershipImpl.java index a0c09cbfb..61f233d88 100644 --- a/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ResultExpressionMembershipImpl.java +++ b/backend/metamodel/syson-sysml-metamodel/src/main/java/org/eclipse/syson/sysml/impl/ResultExpressionMembershipImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* -* Copyright (c) 2023, 2025 Obeo. +* Copyright (c) 2023, 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 @@ -66,13 +66,14 @@ public Expression getOwnedResultExpression() { /** * * - * @generated + * @generated NOT */ public Expression basicGetOwnedResultExpression() { - // TODO: implement this method to return the 'Owned Result Expression' reference - // -> do not perform proxy resolution - // Ensure that you remove @generated or mark it @generated NOT - return null; + return this.getOwnedRelatedElement().stream() + .filter(Expression.class::isInstance) + .map(Expression.class::cast) + .findFirst() + .orElse(null); } /** diff --git a/backend/services/syson-sysml-metamodel-services/src/main/java/org/eclipse/syson/sysml/metamodel/services/MetamodelQueryElementService.java b/backend/services/syson-sysml-metamodel-services/src/main/java/org/eclipse/syson/sysml/metamodel/services/MetamodelQueryElementService.java index d47f02ac6..97b53b28e 100644 --- a/backend/services/syson-sysml-metamodel-services/src/main/java/org/eclipse/syson/sysml/metamodel/services/MetamodelQueryElementService.java +++ b/backend/services/syson-sysml-metamodel-services/src/main/java/org/eclipse/syson/sysml/metamodel/services/MetamodelQueryElementService.java @@ -27,11 +27,16 @@ import org.eclipse.syson.sysml.Feature; import org.eclipse.syson.sysml.FeatureValue; import org.eclipse.syson.sysml.FramedConcernMembership; +import org.eclipse.syson.sysml.OwningMembership; import org.eclipse.syson.sysml.PartUsage; import org.eclipse.syson.sysml.ReferenceUsage; import org.eclipse.syson.sysml.StakeholderMembership; import org.eclipse.syson.sysml.SubjectMembership; +import org.eclipse.syson.sysml.SysmlFactory; import org.eclipse.syson.sysml.Usage; +import org.eclipse.syson.sysml.textual.SysMLElementSerializer; +import org.eclipse.syson.sysml.textual.SysMLSerializingOptions; +import org.eclipse.syson.sysml.textual.utils.FileNameDeresolver; /** * Element-related services doing queries. This class should not depend on sirius-web services or other spring services. @@ -120,6 +125,94 @@ public boolean isTopLevelExpression(Element element) { return result; } + /** + * Check is a given {@code element} has a single/non-ambiguous existing {@link Expression} definition associated. + * + * @param element + * the element to test + * @return true if the element has a single existing associated expression definition. + */ + public boolean hasSingleExpressionDefinition(Element element) { + return this.findSingleExpressionDefinition(element).isPresent(); + } + + /** + * Check whether a given {@link Element element} can contain an {@link Expression}. + * + * @param element + * the element to test. + * @return true if the element can contain an expression. + */ + public boolean canContainExpressionDefinition(Element element) { + return !this.getCompatibleExpressionOwnerships(element).isEmpty(); + } + + /** + * Given an {@link Element element}, returns the list of all {@link OwningMembership owning memberships} through + * which it can contain an {@link Expression expression}. + * + * @param element + * a SysML {@link Element element}. + * @return the owning memberships through which the element may contain an expression. + */ + public List getCompatibleExpressionOwnerships(Element element) { + var result = new ArrayList(); + + // KerML 8.3.4.10.2 FeatureValue: "A FeatureValue is a Membership that identifies a particular member + // Expression that provides the value of the Feature that owns the FeatureValue." + if (element instanceof Feature) { + result.add(SysmlFactory.eINSTANCE.createFeatureValue()); + } + + return result; + } + + /** + * Check is a given {@code element} has a single/non-ambiguous existing {@link Expression} definition associated. + * + * @param element + * the element to test + * @return true if the element has a single existing associated expression definition. + */ + public Optional findSingleExpressionDefinition(Element element) { + Optional result = Optional.empty(); + if (this.isExpressionDefinition(element)) { + result = Optional.of((Expression) element); + } else { + var ownedExpressions = element.getOwnedElement().stream().filter(child -> this.isExpressionDefinition(child)).toList(); + if (ownedExpressions.size() == 1) { + result = Optional.of((Expression) ownedExpressions.get(0)); + } + } + return result; + } + + /** + * Returns the textual representation of an {@link Expression expression}. + * + * @param expression + * an expression. + * @return its textual representation/serialization. + */ + public String getExpressionTextualRepresentation(Expression expression) { + String result = ""; + if (expression != null) { + SysMLSerializingOptions options = new SysMLSerializingOptions.Builder() + .lineSeparator("\n") + .nameDeresolver(new FileNameDeresolver()) + .indentation("\t") + .needEscapeCharacter(false) + .build(); + String textualFormat = new SysMLElementSerializer(options, s -> { + // Do nothing for now + }).doSwitch(expression); + if (textualFormat != null) { + result = textualFormat; + } + } + return result; + } + /** * Get the source of a {@link Connector}. * diff --git a/backend/services/syson-tree-services/src/main/java/org/eclipse/syson/tree/explorer/services/SysONDefaultExplorerServices.java b/backend/services/syson-tree-services/src/main/java/org/eclipse/syson/tree/explorer/services/SysONDefaultExplorerServices.java index 906e39d7b..eaf370209 100644 --- a/backend/services/syson-tree-services/src/main/java/org/eclipse/syson/tree/explorer/services/SysONDefaultExplorerServices.java +++ b/backend/services/syson-tree-services/src/main/java/org/eclipse/syson/tree/explorer/services/SysONDefaultExplorerServices.java @@ -42,9 +42,6 @@ import org.eclipse.syson.sysml.Type; import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; -import org.eclipse.syson.sysml.textual.SysMLElementSerializer; -import org.eclipse.syson.sysml.textual.SysMLSerializingOptions; -import org.eclipse.syson.sysml.textual.utils.FileNameDeresolver; import org.eclipse.syson.sysml.util.ElementUtil; import org.eclipse.syson.tree.explorer.fragments.KerMLStandardLibraryDirectory; import org.eclipse.syson.tree.explorer.fragments.LibrariesDirectory; @@ -157,7 +154,7 @@ public String getLabel(Object self) { if (self instanceof ISysONExplorerFragment fragment) { label = fragment.getLabel(); } else if (self instanceof Expression expression && this.metamodelQueryElementService.isExpressionDefinition(expression)) { - label = this.getValueExpressionTextualRepresentation(expression); + label = this.metamodelQueryElementService.getExpressionTextualRepresentation(expression); } else if (self instanceof Type type) { String name = type.getName(); if (name != null) { @@ -169,25 +166,6 @@ public String getLabel(Object self) { return label; } - private String getValueExpressionTextualRepresentation(Expression value) { - String result = ""; - if (value != null) { - SysMLSerializingOptions options = new SysMLSerializingOptions.Builder() - .lineSeparator("\n") - .nameDeresolver(new FileNameDeresolver()) - .indentation("\t") - .needEscapeCharacter(false) - .build(); - String textualFormat = new SysMLElementSerializer(options, s -> { - // Do nothing for now - }).doSwitch(value); - if (textualFormat != null) { - result = textualFormat; - } - } - return result; - } - private String getFallbackLabel(Object self) { StyledString styledLabel = this.labelService.getStyledLabel(self); if (styledLabel != null) { @@ -264,7 +242,7 @@ public boolean canExpandAll(TreeItem treeItem, IEditingContext editingContext) { @Override public boolean canCreateNewObjectsFromText(Object self) { - return self instanceof Element && this.isEditable(self); + return self instanceof Element element && !this.readOnlyObjectPredicate.test(element); } @Override @@ -303,7 +281,7 @@ public boolean isEditable(Object self) { if (self instanceof ISysONExplorerFragment fragment) { result = fragment.isEditable(); } else if (self instanceof Element element) { - result = !this.readOnlyObjectPredicate.test(element); + result = !this.readOnlyObjectPredicate.test(element) && !this.metamodelQueryElementService.isExpressionDefinition(element); } else if (self instanceof Resource resource) { result = !this.readOnlyObjectPredicate.test(resource); } diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/menu/context/SysONExplorerTreeItemContextMenuEntryProvider.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/menu/context/SysONExplorerTreeItemContextMenuEntryProvider.java index ac4f90efe..9e4dee378 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/menu/context/SysONExplorerTreeItemContextMenuEntryProvider.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/menu/context/SysONExplorerTreeItemContextMenuEntryProvider.java @@ -27,6 +27,7 @@ import org.eclipse.sirius.components.collaborative.trees.dto.SingleClickTreeItemContextMenuEntry; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IObjectSearchService; +import org.eclipse.sirius.components.core.api.IReadOnlyObjectPredicate; import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; import org.eclipse.sirius.components.trees.Tree; import org.eclipse.sirius.components.trees.TreeItem; @@ -43,6 +44,7 @@ import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.Relationship; import org.eclipse.syson.sysml.ViewUsage; +import org.eclipse.syson.sysml.metamodel.services.MetamodelQueryElementService; import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerService; import org.eclipse.syson.tree.explorer.view.SysONTreeViewDescriptionProvider; import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers; @@ -60,6 +62,12 @@ public class SysONExplorerTreeItemContextMenuEntryProvider implements ITreeItemC public static final String NEW_OBJECTS_FROM_TEXT_MENU_ENTRY_CONTRIBUTION_ID = "newObjectsFromText"; + public static final String CREATE_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID = "createExpression"; + + public static final String EDIT_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID = "editExpression"; + + public static final String DELETE_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID = "deleteExpression"; + private final IObjectSearchService objectSearchService; private final ILibrarySearchService librarySearchService; @@ -72,15 +80,21 @@ public class SysONExplorerTreeItemContextMenuEntryProvider implements ITreeItemC private final ISysONExplorerService sysonExplorerService; + private final IReadOnlyObjectPredicate readOnlyObjectPredicate; + + private final MetamodelQueryElementService metamodelQueryElementService; + public SysONExplorerTreeItemContextMenuEntryProvider(IObjectSearchService objectSearchService, ILibrarySearchService librarySearchService, ISemanticDataSearchService semanticDataSearchService, IRepresentationMetadataSearchService representationMetadataSearchService, - SysONTreeViewDescriptionProvider sysONTreeViewDescriptionProvider, ISysONExplorerService sysonExplorerService) { + SysONTreeViewDescriptionProvider sysONTreeViewDescriptionProvider, ISysONExplorerService sysonExplorerService, IReadOnlyObjectPredicate readOnlyObjectPredicate) { this.objectSearchService = Objects.requireNonNull(objectSearchService); this.librarySearchService = Objects.requireNonNull(librarySearchService); this.semanticDataSearchService = Objects.requireNonNull(semanticDataSearchService); this.representationMetadataSearchService = Objects.requireNonNull(representationMetadataSearchService); this.sysONTreeViewDescriptionProvider = Objects.requireNonNull(sysONTreeViewDescriptionProvider); this.sysonExplorerService = Objects.requireNonNull(sysonExplorerService); + this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate); + this.metamodelQueryElementService = new MetamodelQueryElementService(); } @Override @@ -122,38 +136,70 @@ private List getDocumentContextMenuEntries(IEMFEditin } private List getObjectContextMenuEntries(IEMFEditingContext editingContext, TreeItem treeItem) { + List entries = new ArrayList<>(); var optionalEObject = this.objectSearchService.getObject(editingContext, treeItem.getId()) .filter(EObject.class::isInstance) .map(EObject.class::cast); if (optionalEObject.isPresent()) { var object = optionalEObject.get(); if (this.sysonExplorerService.isEditable(object)) { - List entries = new ArrayList<>(); entries.add(new SingleClickTreeItemContextMenuEntry(ExplorerTreeItemContextMenuEntryProvider.NEW_OBJECT, "", List.of(), false, List.of())); - if (object instanceof ViewUsage) { - Optional semanticDataId = new UUIDParser().parse(editingContext.getId()); - var sysonRepresentationAlreadyExists = this.representationMetadataSearchService - .findAllRepresentationMetadataBySemanticDataAndTargetObjectId(AggregateReference.to(semanticDataId.get()), treeItem.getId()).stream() - .anyMatch(rm -> SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID.equals(rm.getDescriptionId()) - || SysONRepresentationDescriptionIdentifiers.REQUIREMENTS_TABLE_VIEW_DESCRIPTION_ID.equals(rm.getDescriptionId())); - if (!sysonRepresentationAlreadyExists) { - entries.add(new SingleClickTreeItemContextMenuEntry(ExplorerTreeItemContextMenuEntryProvider.NEW_REPRESENTATION, "", List.of(), false, List.of())); - } - } else { + if (this.canHaveNewRepresentation(editingContext, treeItem.getId(), object)) { entries.add(new SingleClickTreeItemContextMenuEntry(ExplorerTreeItemContextMenuEntryProvider.NEW_REPRESENTATION, "", List.of(), false, List.of())); } - entries.add(new SingleClickTreeItemContextMenuEntry(NEW_OBJECTS_FROM_TEXT_MENU_ENTRY_CONTRIBUTION_ID, "", List.of(), false, List.of())); + if (this.canHaveNewExpression(editingContext, treeItem.getId(), object)) { + entries.add(new SingleClickTreeItemContextMenuEntry(CREATE_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID, "", List.of(), false, List.of())); + } if (object instanceof Element && !(object instanceof Relationship)) { entries.add(new SingleClickTreeItemContextMenuEntry(ExplorerTreeItemContextMenuEntryProvider.DUPLICATE_OBJECT, "", List.of(), false, List.of())); } - return entries; + } + if (!this.readOnlyObjectPredicate.test(object) && object instanceof Element element) { + this.addExpressionEditionEntries(entries, element); } } - return List.of(); + return entries; + } + + private boolean canHaveNewRepresentation(IEMFEditingContext editingContext, String treeItemId, EObject object) { + boolean result = true; + if (object instanceof ViewUsage) { + Optional semanticDataId = new UUIDParser().parse(editingContext.getId()); + var sysonRepresentationAlreadyExists = this.representationMetadataSearchService + .findAllRepresentationMetadataBySemanticDataAndTargetObjectId(AggregateReference.to(semanticDataId.get()), treeItemId).stream() + .anyMatch(rm -> SysONRepresentationDescriptionIdentifiers.GENERAL_VIEW_DIAGRAM_DESCRIPTION_ID.equals(rm.getDescriptionId()) + || SysONRepresentationDescriptionIdentifiers.REQUIREMENTS_TABLE_VIEW_DESCRIPTION_ID.equals(rm.getDescriptionId())); + if (sysonRepresentationAlreadyExists) { + result = false; + } + } + return result; } + private boolean canHaveNewExpression(IEMFEditingContext editingContext, String treeItemId, EObject object) { + return !this.readOnlyObjectPredicate.test(object) && object instanceof Element element && this.metamodelQueryElementService.canContainExpressionDefinition(element) + && !this.metamodelQueryElementService.hasSingleExpressionDefinition(element); + } + + private void addExpressionEditionEntries(List entries, Element element) { + var expressionEntries = new ArrayList(); + + // "Edit expression" on the root Expression element itself; the normal "Delete" operation works on it so no need + // to also add "Delete expression" + if (this.metamodelQueryElementService.isTopLevelExpression(element)) { + expressionEntries.add(EDIT_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID); + } else if (this.metamodelQueryElementService.hasSingleExpressionDefinition(element) + && !this.metamodelQueryElementService.hasSingleExpressionDefinition(element.getOwner())) { + // "Delete expression" on the owner of a root Expression element + expressionEntries.add(DELETE_EXPRESSION_MENU_ENTRY_CONTRIBUTION_ID); + } + + expressionEntries.forEach(id -> entries.add(new SingleClickTreeItemContextMenuEntry(id, "", List.of(), false, List.of()))); + } + + private List getRepresentationContextMenuEntries(IEMFEditingContext editingContext, TreeItem treeItem) { var optionalRepresentationMetadata = this.objectSearchService.getObject(editingContext, treeItem.getId()) .filter(RepresentationMetadata.class::isInstance) diff --git a/doc/content/modules/user-manual/assets/images/edit-expression-modal-error.png b/doc/content/modules/user-manual/assets/images/edit-expression-modal-error.png new file mode 100644 index 0000000000000000000000000000000000000000..05ccb2d1471d55a3f77708d97f53a219f4537994 GIT binary patch literal 70881 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 literal 0 HcmV?d00001 diff --git a/doc/content/modules/user-manual/assets/images/edit-expression-modal.png b/doc/content/modules/user-manual/assets/images/edit-expression-modal.png new file mode 100644 index 0000000000000000000000000000000000000000..6304b96ea632b1b9a286529a3eb904e5effab144 GIT binary patch literal 38663 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 U_MxH)yWhYACCz(i1*>QO3s?jBrT_o{ literal 0 HcmV?d00001 diff --git a/doc/content/modules/user-manual/assets/images/explorer-expression-full-text.png b/doc/content/modules/user-manual/assets/images/explorer-expression-full-text.png new file mode 100644 index 0000000000000000000000000000000000000000..1a2c26dee8f955e4c1c8e4dd50662bcdfbc5309a GIT binary patch literal 39582 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