From 378a452c3eb511bdc8e3c10c4af4c425ab103da1 Mon Sep 17 00:00:00 2001 From: Gwendal Daniel Date: Fri, 28 Feb 2025 15:19:25 +0100 Subject: [PATCH] [4652] Add support for project to library dependencies Bug: https://github.com/eclipse-sirius/sirius-web/issues/4652 Signed-off-by: Gwendal Daniel --- CHANGELOG.adoc | 4 + .../services/EditingContextLoader.java | 8 +- .../services/EditingContextLibraryLoader.java | 101 ++++++++++++++++++ .../api/IEditingContextLibraryLoader.java | 28 +++++ .../ComposedReadOnlyObjectPredicate.java | 52 +++++++++ .../DefaultReadOnlyObjectPredicate.java | 48 +++++++++ .../api/IDefaultReadOnlyObjectPredicate.java | 24 +++++ .../api/IReadOnlyObjectPredicate.java | 24 +++++ .../api/IReadOnlyObjectPredicateDelegate.java | 26 +++++ .../explorer/services/ExplorerServices.java | 22 ++-- .../boundedcontexts/library/Library.java | 14 +++ .../services/LibrarySearchService.java | 32 ++++++ .../services/api/ILibrarySearchService.java | 6 ++ .../semanticdata/SemanticData.java | 31 ++++++ .../semanticdata/SemanticDataDependency.java | 30 ++++++ .../SemanticDataDependencyAddedEvent.java | 35 ++++++ .../SemanticDataDependencyRemovedEvent.java | 35 ++++++ .../services/SemanticDataUpdateService.java | 43 +++++++- .../api/ISemanticDataUpdateService.java | 6 ++ .../02-add-semantic-data-dependency-table.xml | 35 ++++++ .../db/changelog/2025.4/2025.4.0.xml | 1 + .../LibraryControllerIntegrationTests.java | 62 +++++++++++ 22 files changed, 657 insertions(+), 10 deletions(-) create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/EditingContextLibraryLoader.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/api/IEditingContextLibraryLoader.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/ComposedReadOnlyObjectPredicate.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/DefaultReadOnlyObjectPredicate.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IDefaultReadOnlyObjectPredicate.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicate.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicateDelegate.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticDataDependency.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyAddedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyRemovedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/02-add-semantic-data-dependency-table.xml diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 52501b1061..75dfa69b06 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -45,6 +45,10 @@ See the new interface `org.eclipse.sirius.components.emf.services.api.IRepresent - https://github.com/eclipse-sirius/sirius-web/issues/4597[#4597] [sirius-web] Add a command to publish libraries from studios The command creates a library for each _RepresentationDescription_ and _Domain_ in the studio, and creates the dependencies between them. A _shared components_ library can be created in the process to store elements that are needed by other libraries but are not stored in libraries themselves. +- https://github.com/eclipse-sirius/sirius-web/issues/4652[#4652] [sirius-web] Add support for project to library dependencies +Project can have dependencies to libraries, which are loaded along the project's semantic data. +Loading a library in the editing context loads all the libraries it transitively depends on. +A new predicate `IReadOnlyObjectPredicate` has been added with a default implementation that returns `true` if the object is in a library. === Improvements diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextLoader.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextLoader.java index 9cfa9b15ae..dea4f987c6 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextLoader.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextLoader.java @@ -24,6 +24,7 @@ import org.eclipse.sirius.web.application.editingcontext.services.api.IEditingContextLoader; import org.eclipse.sirius.web.application.editingcontext.services.api.IEditingContextMigrationParticipantPredicate; import org.eclipse.sirius.web.application.editingcontext.services.api.IResourceLoader; +import org.eclipse.sirius.web.application.library.services.api.IEditingContextLibraryLoader; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,22 +42,27 @@ public class EditingContextLoader implements IEditingContextLoader { private final IResourceLoader resourceLoader; + private final IEditingContextLibraryLoader editingContextLibraryLoader; + private final List representationDescriptionProviders; private final List editingContextProcessors; private final List migrationParticipantPredicates; - public EditingContextLoader(IResourceLoader resourceLoader, List representationDescriptionProviders, List editingContextProcessors, List migrationParticipantPredicates) { + public EditingContextLoader(IResourceLoader resourceLoader, IEditingContextLibraryLoader editingContextLibraryLoader, List representationDescriptionProviders, List editingContextProcessors, List migrationParticipantPredicates) { this.resourceLoader = Objects.requireNonNull(resourceLoader); + this.editingContextLibraryLoader = Objects.requireNonNull(editingContextLibraryLoader); this.representationDescriptionProviders = Objects.requireNonNull(representationDescriptionProviders); this.editingContextProcessors = Objects.requireNonNull(editingContextProcessors); this.migrationParticipantPredicates = Objects.requireNonNull(migrationParticipantPredicates); } + @Override public void load(EditingContext editingContext, SemanticData semanticData) { this.editingContextProcessors.forEach(processor -> processor.preProcess(editingContext)); + this.editingContextLibraryLoader.loadLibraries(editingContext); this.loadSemanticData(editingContext, semanticData); this.representationDescriptionProviders.forEach(representationDescriptionProvider -> { diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/EditingContextLibraryLoader.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/EditingContextLibraryLoader.java new file mode 100644 index 0000000000..d978afe36d --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/EditingContextLibraryLoader.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.library.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.web.application.UUIDParser; +import org.eclipse.sirius.web.application.editingcontext.EditingContext; +import org.eclipse.sirius.web.application.editingcontext.services.api.IEditingContextMigrationParticipantPredicate; +import org.eclipse.sirius.web.application.editingcontext.services.api.IResourceLoader; +import org.eclipse.sirius.web.application.library.services.api.IEditingContextLibraryLoader; +import org.eclipse.sirius.web.domain.boundedcontexts.library.Library; +import org.eclipse.sirius.web.domain.boundedcontexts.library.services.api.ILibrarySearchService; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticDataDependency; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataSearchService; +import org.springframework.stereotype.Service; + +/** + * Loads libraries into the editing context. + * + * @author gdaniel + */ +@Service +public class EditingContextLibraryLoader implements IEditingContextLibraryLoader { + + private final ISemanticDataSearchService semanticDataSearchService; + + private final ILibrarySearchService librarySearchService; + + private final IResourceLoader resourceLoader; + + private final List migrationParticipantPredicates; + + public EditingContextLibraryLoader(ISemanticDataSearchService semanticDataSearchService, ILibrarySearchService librarySearchService, IResourceLoader resourceLoader, List migrationParticipantPredicates) { + this.semanticDataSearchService = Objects.requireNonNull(semanticDataSearchService); + this.librarySearchService = Objects.requireNonNull(librarySearchService); + this.resourceLoader = Objects.requireNonNull(resourceLoader); + this.migrationParticipantPredicates = Objects.requireNonNull(migrationParticipantPredicates); + } + + @Override + public void loadLibraries(IEditingContext editingContext) { + if (editingContext instanceof EditingContext siriusWebEditingContext) { + Set librariesToLoad = this.getLibrariesToLoad(siriusWebEditingContext); + for (Library library : librariesToLoad) { + Optional librarySemanticData = this.semanticDataSearchService.findById(library.getSemanticData().getId()); + if (librarySemanticData.isPresent()) { + librarySemanticData.get().getDocuments().forEach(document -> { + URI libraryResourceURI = URI.createURI(LIBRARY_SCHEME + ":///" + document.getId().toString()); + if (siriusWebEditingContext.getDomain().getResourceSet().getResource(libraryResourceURI, false) == null) { + Optional resource = this.resourceLoader.toResource(siriusWebEditingContext.getDomain().getResourceSet(), document.getId().toString(), document.getName(), document.getContent(), + this.migrationParticipantPredicates.stream().anyMatch(predicate -> predicate.test(editingContext.getId()))); + resource.ifPresent(r -> { + siriusWebEditingContext.getDomain().getResourceSet().getURIConverter().getURIMap().put(r.getURI(), libraryResourceURI); + r.setURI(libraryResourceURI); + }); + } + }); + } + } + } + } + + private Set getLibrariesToLoad(EditingContext editingContext) { + Set librariesToLoad = new LinkedHashSet<>(); + List editingContextLibraries = new UUIDParser().parse(editingContext.getId()) + .flatMap(semanticDataId -> this.semanticDataSearchService.findById(semanticDataId)) + .map(SemanticData::getDependencies) + .orElse(List.of()) + .stream() + .map(SemanticDataDependency::libraryId) + .map(this.librarySearchService::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .toList(); + + for (Library library : editingContextLibraries) { + librariesToLoad.add(library); + librariesToLoad.addAll(this.librarySearchService.findAllTransitiveDependencyLibrariesByLibrary(library)); + } + return librariesToLoad; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/api/IEditingContextLibraryLoader.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/api/IEditingContextLibraryLoader.java new file mode 100644 index 0000000000..18dc18dfe3 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/library/services/api/IEditingContextLibraryLoader.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.library.services.api; + +import org.eclipse.sirius.components.core.api.IEditingContext; + +/** + * Loads libraries into the editing context. + * + * @author gdaniel + */ +public interface IEditingContextLibraryLoader { + + String LIBRARY_SCHEME = "library"; + + void loadLibraries(IEditingContext editingContext); + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/ComposedReadOnlyObjectPredicate.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/ComposedReadOnlyObjectPredicate.java new file mode 100644 index 0000000000..b14d6849cd --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/ComposedReadOnlyObjectPredicate.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.object.services; + +import java.util.List; +import java.util.Objects; + +import org.eclipse.sirius.web.application.object.services.api.IDefaultReadOnlyObjectPredicate; +import org.eclipse.sirius.web.application.object.services.api.IReadOnlyObjectPredicate; +import org.eclipse.sirius.web.application.object.services.api.IReadOnlyObjectPredicateDelegate; +import org.springframework.stereotype.Service; + +/** + * Implementation of {@link IReadOnlyObjectPredicate} which delegates to {@link IReadOnlyObjectPredicateDelegate} or fallback to + * {@link IDefaultReadOnlyObjectPredicate}. + * + * @author gdaniel + */ +@Service +public class ComposedReadOnlyObjectPredicate implements IReadOnlyObjectPredicate { + + private final List readOnlyObjectPredicateDelegate; + + private final IDefaultReadOnlyObjectPredicate defaultReadOnlyObjectPredicate; + + public ComposedReadOnlyObjectPredicate(List readOnlyObjectPredicateDelegate, IDefaultReadOnlyObjectPredicate defaultReadOnlyObjectPredicate) { + this.readOnlyObjectPredicateDelegate = Objects.requireNonNull(readOnlyObjectPredicateDelegate); + this.defaultReadOnlyObjectPredicate = Objects.requireNonNull(defaultReadOnlyObjectPredicate); + } + + @Override + public boolean test(Object object) { + var optionalDelegate = this.readOnlyObjectPredicateDelegate.stream() + .filter(delegate -> delegate.canHandle(object)) + .findFirst(); + if (optionalDelegate.isPresent()) { + return optionalDelegate.get().test(object); + } + return this.defaultReadOnlyObjectPredicate.test(object); + } + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/DefaultReadOnlyObjectPredicate.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/DefaultReadOnlyObjectPredicate.java new file mode 100644 index 0000000000..5647771dea --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/DefaultReadOnlyObjectPredicate.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.object.services; + +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.sirius.web.application.library.services.api.IEditingContextLibraryLoader; +import org.eclipse.sirius.web.application.object.services.api.IDefaultReadOnlyObjectPredicate; +import org.springframework.stereotype.Service; + +/** + * The default service used to test if an object is read-only. + * + * @author gdaniel + */ +@Service +public class DefaultReadOnlyObjectPredicate implements IDefaultReadOnlyObjectPredicate { + + @Override + public boolean test(Object object) { + boolean result = false; + if (object instanceof EObject eObject) { + result = Optional.ofNullable(eObject.eResource()) + .map(Resource::getURI) + .map(URI::scheme) + .filter(scheme -> Objects.equals(scheme, IEditingContextLibraryLoader.LIBRARY_SCHEME)) + .isPresent(); + } else if (object instanceof Resource resource) { + result = Objects.equals(resource.getURI().scheme(), IEditingContextLibraryLoader.LIBRARY_SCHEME); + } + return result; + } + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IDefaultReadOnlyObjectPredicate.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IDefaultReadOnlyObjectPredicate.java new file mode 100644 index 0000000000..532ddba284 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IDefaultReadOnlyObjectPredicate.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.object.services.api; + +import java.util.function.Predicate; + +/** + * The default service used to test if an object is read-only. + * + * @author gdaniel + */ +public interface IDefaultReadOnlyObjectPredicate extends Predicate { + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicate.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicate.java new file mode 100644 index 0000000000..c16a18bea5 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicate.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.object.services.api; + +import java.util.function.Predicate; + +/** + * Used to test if an object is read-only. + * + * @author gdaniel + */ +public interface IReadOnlyObjectPredicate extends Predicate { + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicateDelegate.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicateDelegate.java new file mode 100644 index 0000000000..2562fd1417 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/object/services/api/IReadOnlyObjectPredicateDelegate.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.application.object.services.api; + +import java.util.function.Predicate; + +/** + * Used to test if an object is read-only. + * + * @author gdaniel + */ +public interface IReadOnlyObjectPredicateDelegate extends Predicate { + + boolean canHandle(Object object); + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/explorer/services/ExplorerServices.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/explorer/services/ExplorerServices.java index 83a7135d64..a73c3a8753 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/explorer/services/ExplorerServices.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/explorer/services/ExplorerServices.java @@ -33,6 +33,7 @@ import org.eclipse.sirius.components.emf.services.JSONResourceFactory; import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; import org.eclipse.sirius.web.application.UUIDParser; +import org.eclipse.sirius.web.application.object.services.api.IReadOnlyObjectPredicate; import org.eclipse.sirius.web.application.views.explorer.services.api.IExplorerServices; import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationIconURL; import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata; @@ -56,11 +57,14 @@ public class ExplorerServices implements IExplorerServices { private final IRepresentationMetadataSearchService representationMetadataSearchService; - public ExplorerServices(IObjectService objectService, IURLParser urlParser, List representationImageProviders, IRepresentationMetadataSearchService representationMetadataSearchService) { + private final IReadOnlyObjectPredicate readOnlyObjectPredicate; + + public ExplorerServices(IObjectService objectService, IURLParser urlParser, List representationImageProviders, IRepresentationMetadataSearchService representationMetadataSearchService, IReadOnlyObjectPredicate readOnlyObjectPredicate) { this.objectService = Objects.requireNonNull(objectService); this.urlParser = Objects.requireNonNull(urlParser); this.representationImageProviders = Objects.requireNonNull(representationImageProviders); this.representationMetadataSearchService = Objects.requireNonNull(representationMetadataSearchService); + this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate); } @Override @@ -114,19 +118,21 @@ private String getResourceLabel(Resource resource) { @Override public boolean isEditable(Object self) { boolean editable = false; - if (self instanceof RepresentationMetadata) { - editable = true; - } else if (self instanceof Resource) { - editable = true; - } else if (self instanceof EObject) { - editable = this.objectService.isLabelEditable(self); + if (!this.readOnlyObjectPredicate.test(self)) { + if (self instanceof RepresentationMetadata) { + editable = true; + } else if (self instanceof Resource) { + editable = true; + } else if (self instanceof EObject) { + editable = this.objectService.isLabelEditable(self); + } } return editable; } @Override public boolean isDeletable(Object self) { - return true; + return !this.readOnlyObjectPredicate.test(self); } @Override diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/Library.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/Library.java index 2c818ac062..06088f54f4 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/Library.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/Library.java @@ -109,6 +109,20 @@ public static Builder newLibrary() { return new Builder(); } + @Override + public boolean equals(Object obj) { + boolean result = false; + if (obj instanceof Library library) { + result = Objects.equals(this.id, library.getId()); + } + return result; + } + + @Override + public int hashCode() { + return this.id.hashCode(); + } + /** * Used to create new libraries. * diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/LibrarySearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/LibrarySearchService.java index 78059cacb0..ed6d5d4410 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/LibrarySearchService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/LibrarySearchService.java @@ -12,14 +12,19 @@ *******************************************************************************/ package org.eclipse.sirius.web.domain.boundedcontexts.library.services; +import java.util.LinkedHashSet; import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.UUID; import org.eclipse.sirius.web.domain.boundedcontexts.library.Library; +import org.eclipse.sirius.web.domain.boundedcontexts.library.LibraryDependency; import org.eclipse.sirius.web.domain.boundedcontexts.library.repositories.ILibraryRepository; import org.eclipse.sirius.web.domain.boundedcontexts.library.services.api.ILibrarySearchService; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jdbc.core.mapping.AggregateReference; import org.springframework.stereotype.Service; /** @@ -50,4 +55,31 @@ public boolean existsByNamespaceAndNameAndVersion(String namespace, String name, public Optional findByNamespaceAndNameAndVersion(String namespace, String name, String version) { return this.libraryRepository.findByNamespaceAndNameAndVersion(namespace, name, version); } + + @Override + public Optional findById(UUID id) { + return this.libraryRepository.findById(id); + } + + @Override + public Set findAllTransitiveDependencyLibrariesByLibrary(Library library) { + Set collectedLibraries = new LinkedHashSet<>(); + this.collectLibraryDependencies(library, collectedLibraries); + return collectedLibraries; + } + + private void collectLibraryDependencies(Library library, Set collectedLibraries) { + if (!collectedLibraries.contains(library)) { + library.getDependencies().stream() + .map(LibraryDependency::dependencyLibraryId) + .map(AggregateReference::getId) + .map(this.libraryRepository::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .forEach(dependency -> { + collectedLibraries.add(dependency); + this.collectLibraryDependencies(dependency, collectedLibraries); + }); + } + } } diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/api/ILibrarySearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/api/ILibrarySearchService.java index 54325a900d..acaa96f15d 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/api/ILibrarySearchService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/library/services/api/ILibrarySearchService.java @@ -13,6 +13,8 @@ package org.eclipse.sirius.web.domain.boundedcontexts.library.services.api; import java.util.Optional; +import java.util.Set; +import java.util.UUID; import org.eclipse.sirius.web.domain.boundedcontexts.library.Library; import org.springframework.data.domain.Page; @@ -30,4 +32,8 @@ public interface ILibrarySearchService { boolean existsByNamespaceAndNameAndVersion(String namespace, String name, String version); Optional findByNamespaceAndNameAndVersion(String namespace, String name, String version); + + Optional findById(UUID id); + + Set findAllTransitiveDependencyLibrariesByLibrary(Library library); } diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java index cd7b5410ce..681ac54f2a 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java @@ -13,6 +13,7 @@ package org.eclipse.sirius.web.domain.boundedcontexts.semanticdata; import java.time.Instant; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; @@ -24,6 +25,8 @@ import org.eclipse.sirius.components.events.ICause; import org.eclipse.sirius.web.domain.boundedcontexts.AbstractValidatingAggregateRoot; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataCreatedEvent; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataDependencyAddedEvent; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataDependencyRemovedEvent; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataUpdatedEvent; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Transient; @@ -51,6 +54,9 @@ public class SemanticData extends AbstractValidatingAggregateRoot @MappedCollection(idColumn = "semantic_data_id") private Set domains = new LinkedHashSet<>(); + @MappedCollection(idColumn = "semantic_data_id", keyColumn = "index") + private List dependencies = new ArrayList<>(); + private Instant createdOn; private Instant lastModifiedOn; @@ -68,6 +74,31 @@ public Set getDomains() { return Collections.unmodifiableSet(this.domains); } + public List getDependencies() { + return Collections.unmodifiableList(this.dependencies); + } + + public void addDependency(ICause cause, UUID libraryId) { + var newDependency = new SemanticDataDependency(libraryId); + this.dependencies.add(newDependency); + this.lastModifiedOn = Instant.now(); + + this.registerEvent(new SemanticDataDependencyAddedEvent(UUID.randomUUID(), this.lastModifiedOn, cause, this, newDependency)); + + } + + public void removeDependency(ICause cause, UUID libraryId) { + this.dependencies.stream() + .filter(dependency -> dependency.libraryId().equals(libraryId)) + .findFirst() + .ifPresent(dependency -> { + this.dependencies.remove(dependency); + this.lastModifiedOn = Instant.now(); + + this.registerEvent(new SemanticDataDependencyRemovedEvent(UUID.randomUUID(), this.lastModifiedOn, cause, this, dependency)); + }); + } + public Instant getCreatedOn() { return this.createdOn; } diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticDataDependency.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticDataDependency.java new file mode 100644 index 0000000000..f56e95ccdd --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticDataDependency.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.domain.boundedcontexts.semanticdata; + +import java.util.Objects; +import java.util.UUID; + +import org.springframework.data.relational.core.mapping.Table; + +/** + * A dependency of a project. + * + * @author gdaniel + */ +@Table("semantic_data_dependency") +public record SemanticDataDependency(UUID libraryId) { + public SemanticDataDependency { + Objects.requireNonNull(libraryId); + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyAddedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyAddedEvent.java new file mode 100644 index 0000000000..c64830b1ab --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyAddedEvent.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.domain.boundedcontexts.semanticdata.events; + +import java.time.Instant; +import java.util.UUID; + +import org.eclipse.sirius.components.events.ICause; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticDataDependency; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when a dependency is added. + * + * @author gdaniel + */ +public record SemanticDataDependencyAddedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull ICause causedBy, + @NotNull SemanticData semanticData, + @NotNull SemanticDataDependency dependency) implements ISemanticDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyRemovedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyRemovedEvent.java new file mode 100644 index 0000000000..f6a897f0a0 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataDependencyRemovedEvent.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2025 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.sirius.web.domain.boundedcontexts.semanticdata.events; + +import java.time.Instant; +import java.util.UUID; + +import org.eclipse.sirius.components.events.ICause; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticDataDependency; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when a dependency is removed. + * + * @author gdaniel + */ +public record SemanticDataDependencyRemovedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull ICause causedBy, + @NotNull SemanticData semanticData, + @NotNull SemanticDataDependency dependency) implements ISemanticDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java index 846e321c9c..44b889b90f 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java @@ -21,6 +21,10 @@ import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.repositories.ISemanticDataRepository; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataUpdateService; +import org.eclipse.sirius.web.domain.services.Failure; +import org.eclipse.sirius.web.domain.services.IResult; +import org.eclipse.sirius.web.domain.services.Success; +import org.eclipse.sirius.web.domain.services.api.IMessageService; import org.springframework.data.jdbc.core.mapping.AggregateReference; import org.springframework.stereotype.Service; @@ -34,8 +38,11 @@ public class SemanticDataUpdateService implements ISemanticDataUpdateService { private final ISemanticDataRepository semanticDataRepository; - public SemanticDataUpdateService(ISemanticDataRepository semanticDataRepository) { + private final IMessageService messageService; + + public SemanticDataUpdateService(ISemanticDataRepository semanticDataRepository, IMessageService messageService) { this.semanticDataRepository = Objects.requireNonNull(semanticDataRepository); + this.messageService = Objects.requireNonNull(messageService); } @Override @@ -45,4 +52,38 @@ public void updateDocuments(ICause cause, AggregateReference this.semanticDataRepository.save(semanticData); }); } + + @Override + public IResult addDependency(ICause cause, UUID semanticDataId, UUID libraryId) { + IResult result = null; + + var optionalSemanticData = this.semanticDataRepository.findById(semanticDataId); + if (optionalSemanticData.isEmpty()) { + result = new Failure<>(this.messageService.notFound()); + } else { + var semanticData = optionalSemanticData.get(); + semanticData.addDependency(cause, libraryId); + this.semanticDataRepository.save(semanticData); + result = new Success<>(null); + } + + return result; + } + + @Override + public IResult removeDependency(ICause cause, UUID semanticDataId, UUID libraryId) { + IResult result = null; + + var optionalSemanticData = this.semanticDataRepository.findById(semanticDataId); + if (optionalSemanticData.isEmpty()) { + result = new Failure<>(this.messageService.notFound()); + } else { + var semanticData = optionalSemanticData.get(); + semanticData.removeDependency(cause, libraryId); + this.semanticDataRepository.save(semanticData); + result = new Success<>(null); + } + + return result; + } } diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java index 4af5151bf1..803698f8ba 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java @@ -18,6 +18,7 @@ import org.eclipse.sirius.components.events.ICause; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.Document; import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.eclipse.sirius.web.domain.services.IResult; import org.springframework.data.jdbc.core.mapping.AggregateReference; /** @@ -27,4 +28,9 @@ */ public interface ISemanticDataUpdateService { void updateDocuments(ICause cause, AggregateReference semanticData, Set documents, Set domainUris); + + IResult addDependency(ICause cause, UUID semanticDataId, UUID libraryId); + + IResult removeDependency(ICause cause, UUID semanticDataID, UUID libraryId); + } diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/02-add-semantic-data-dependency-table.xml b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/02-add-semantic-data-dependency-table.xml new file mode 100644 index 0000000000..ba918c2fa4 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/02-add-semantic-data-dependency-table.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/2025.4.0.xml b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/2025.4.0.xml index c693701f55..691e631a71 100644 --- a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/2025.4.0.xml +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2025.4/2025.4.0.xml @@ -16,4 +16,5 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd"> + diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/libraries/LibraryControllerIntegrationTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/libraries/LibraryControllerIntegrationTests.java index 7ad8f040a4..4f9d5ac3e2 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/libraries/LibraryControllerIntegrationTests.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/libraries/LibraryControllerIntegrationTests.java @@ -18,17 +18,32 @@ import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.UUID; +import java.util.function.BiFunction; import org.assertj.core.api.InstanceOfAssertFactories; +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.IPayload; import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.emf.ResourceMetadataAdapter; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionInput; +import org.eclipse.sirius.components.graphql.tests.api.IExecuteEditingContextFunctionRunner; import org.eclipse.sirius.web.AbstractIntegrationTests; import org.eclipse.sirius.web.application.library.dto.PublishLibrariesInput; +import org.eclipse.sirius.web.application.library.services.api.IEditingContextLibraryLoader; +import org.eclipse.sirius.web.application.object.services.api.IReadOnlyObjectPredicate; +import org.eclipse.sirius.web.data.PapayaIdentifiers; import org.eclipse.sirius.web.data.StudioIdentifiers; import org.eclipse.sirius.web.domain.boundedcontexts.library.Library; import org.eclipse.sirius.web.domain.boundedcontexts.library.LibraryDependency; import org.eclipse.sirius.web.domain.boundedcontexts.library.services.api.ILibrarySearchService; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataUpdateService; +import org.eclipse.sirius.web.domain.services.Success; import org.eclipse.sirius.web.papaya.services.library.InitializeStandardLibraryEvent; import org.eclipse.sirius.web.papaya.services.library.api.IStandardLibrarySemanticDataInitializer; import org.eclipse.sirius.web.tests.data.GivenSiriusWebServer; @@ -50,6 +65,7 @@ * @author gdaniel */ @Transactional +@SuppressWarnings("checkstyle:MultipleStringLiterals") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class LibraryControllerIntegrationTests extends AbstractIntegrationTests { @@ -65,6 +81,15 @@ public class LibraryControllerIntegrationTests extends AbstractIntegrationTests @Autowired private IStandardLibrarySemanticDataInitializer standardLibrarySemanticDataInitializer; + @Autowired + private ISemanticDataUpdateService semanticDataUpdateService; + + @Autowired + private IExecuteEditingContextFunctionRunner executeEditingContextFunctionRunner; + + @Autowired + private IReadOnlyObjectPredicate readOnlyObjectPredicate; + @BeforeEach public void beforeEach() { // Re-create the Papaya standard library before each test: it will be deleted by the cleanup script. @@ -103,6 +128,43 @@ public void givenSetOfLibrariesWhenQueryIsPerformedThenTheLibrariesAreReturned() .anySatisfy(namespace -> assertThat(namespace).isEqualTo("java")); } + @Test + @GivenSiriusWebServer + @DisplayName("Given a project, when a dependency to a library is added, then the editing context contains the library and the library is read-only") + public void givenProjectWhenLibraryDependencyIsAddedThenEditingContextContainsLibrary() { + Optional library = this.librarySearchService.findByNamespaceAndNameAndVersion("java", "Java Standard Library", "17.0.0"); + assertThat(library).isPresent(); + var result = this.semanticDataUpdateService.addDependency(null, PapayaIdentifiers.PAPAYA_EDITING_CONTEXT_ID, library.get().getId()); + TestTransaction.flagForCommit(); + TestTransaction.end(); + TestTransaction.start(); + assertThat(result).isInstanceOf(Success.class); + + + BiFunction function = (editingContext, executeEditingContextFunctionInput) -> { + if (editingContext instanceof IEMFEditingContext emfEditingContext) { + assertThat(emfEditingContext.getDomain().getResourceSet().getResources()) + .anyMatch(resource -> { + Optional optName = resource.eAdapters().stream() + .filter(ResourceMetadataAdapter.class::isInstance) + .map(ResourceMetadataAdapter.class::cast) + .map(ResourceMetadataAdapter::getName) + .findFirst(); + return optName.isPresent() + && optName.get().equals("Java Standard Library") + && Objects.equals(resource.getURI().scheme(), IEditingContextLibraryLoader.LIBRARY_SCHEME) + && this.readOnlyObjectPredicate.test(resource); + }); + return new SuccessPayload(executeEditingContextFunctionInput.id()); + } + return new ErrorPayload(executeEditingContextFunctionInput.id(), "Invalid editing context"); + }; + + var input = new ExecuteEditingContextFunctionInput(UUID.randomUUID(), PapayaIdentifiers.PAPAYA_EDITING_CONTEXT_ID.toString(), function); + var payload = this.executeEditingContextFunctionRunner.execute(input).block(); + assertThat(payload).isInstanceOf(SuccessPayload.class); + } + @Test @GivenSiriusWebServer @DisplayName("Given a valid studio project ID, when the publication mutation is performed, then the libraries are published")