From 361aa01b79634cda71089049166fd13e883216e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20B=C3=A9gaudeau?= Date: Fri, 9 Feb 2024 15:18:43 +0100 Subject: [PATCH] [3021] Improve the new architecture with representation and semantic data related code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://github.com/eclipse-sirius/sirius-web/issues/3021 Signed-off-by: Stéphane Bégaudeau --- .../backend/sirius-web-application/pom.xml | 15 ++ .../editingcontext/EditingContext.java | 64 +++++++ .../services/DomainSearchService.java | 69 +++++++ .../EditingContextEPackageService.java | 32 ++++ .../EditingContextPersistenceService.java | 120 +++++++++++++ .../services/EditingContextSearchService.java | 149 ++++++++++++++++ .../services/EditingDomainFactory.java | 79 ++++++++ .../services/api/IEditingDomainFactory.java | 39 ++++ ...DanglingRepresentationDeletionService.java | 36 ++++ ...epresentationDescriptionSearchService.java | 50 ++++++ .../RepresentationMetadataSearchService.java | 60 +++++++ .../RepresentationPersistenceService.java | 31 ++++ .../services/RepresentationSearchService.java | 34 ++++ .../listeners/SemanticDataInitializer.java | 43 +++++ .../web/application/viewer/DefaultViewer.java | 21 +++ .../web/application/viewer/IViewer.java | 21 +++ .../controllers/QueryViewDataFetcher.java | 33 ++++ .../src/main/resources/.gitkeep | 0 .../main/resources/schema/siriusweb.graphqls | 43 +++++ .../services/ProjectSearchService.java | 9 +- .../services/api/IProjectSearchService.java | 5 +- .../RepresentationData.java | 168 ++++++++++++++++++ .../events/IRepresentationDataEvent.java | 23 +++ .../RepresentationDataCreatedEvent.java | 31 ++++ .../RepresentationDataUpdatedEvent.java | 31 ++++ .../IRepresentationDataRepository.java | 29 +++ .../RepresentationDataCreationService.java | 25 +++ .../RepresentationDataSearchService.java | 39 ++++ .../IRepresentationDataCreationService.java | 21 +++ .../api/IRepresentationDataSearchService.java | 30 ++++ .../semanticdata/Document.java | 104 +++++++++++ .../semanticdata/SemanticData.java | 132 ++++++++++++++ .../events/ISemanticDataEvent.java | 23 +++ .../events/SemanticDataCreatedEvent.java | 31 ++++ .../events/SemanticDataUpdatedEvent.java | 31 ++++ .../repositories/ISemanticDataRepository.java | 45 +++++ .../services/SemanticDataCreationService.java | 48 +++++ .../services/SemanticDataSearchService.java | 49 +++++ .../services/SemanticDataUpdateService.java | 46 +++++ .../api/ISemanticDataCreationService.java | 27 +++ .../api/ISemanticDataSearchService.java | 32 ++++ .../api/ISemanticDataUpdateService.java | 29 +++ .../graphql/GraphQLConfiguration.java | 113 ++++++++++++ .../GraphQLDataFetcherExceptionHandler.java | 48 +++++ .../graphql/GraphQLWiringFactory.java | 50 ++++++ .../monitoring/MonitoringConfiguration.java | 32 ++++ .../changelog/2024.01/01-initial-schema.xml | 76 ++++++++ .../backend/sirius-web-starter/pom.xml | 10 ++ .../SiriusWebStarterConfiguration.java | 35 ++++ .../src/router/RouterExtensionPoints.tsx | 4 +- .../web/backend/sirius-components-web/pom.xml | 8 +- 51 files changed, 2316 insertions(+), 7 deletions(-) create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/EditingContext.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/DomainSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextEPackageService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextPersistenceService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingDomainFactory.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/api/IEditingDomainFactory.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/DanglingRepresentationDeletionService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationDescriptionSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationMetadataSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationPersistenceService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/semanticdata/listeners/SemanticDataInitializer.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/DefaultViewer.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/IViewer.java create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/controllers/QueryViewDataFetcher.java delete mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/resources/.gitkeep create mode 100644 packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/RepresentationData.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/IRepresentationDataEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataCreatedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataUpdatedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/repositories/IRepresentationDataRepository.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataCreationService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataCreationService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/Document.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/ISemanticDataEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataCreatedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataUpdatedEvent.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/repositories/ISemanticDataRepository.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataCreationService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataCreationService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataSearchService.java create mode 100644 packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java create mode 100644 packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLConfiguration.java create mode 100644 packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLDataFetcherExceptionHandler.java create mode 100644 packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLWiringFactory.java create mode 100644 packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/monitoring/MonitoringConfiguration.java diff --git a/packages/sirius-web/backend/sirius-web-application/pom.xml b/packages/sirius-web/backend/sirius-web-application/pom.xml index d6c29e56b6..007a4ad42d 100644 --- a/packages/sirius-web/backend/sirius-web-application/pom.xml +++ b/packages/sirius-web/backend/sirius-web-application/pom.xml @@ -59,6 +59,21 @@ sirius-components-graphql-api 2024.1.2 + + org.eclipse.sirius + sirius-components-collaborative + 2024.1.2 + + + org.eclipse.sirius + sirius-components-emf + 2024.1.2 + + + org.eclipse.sirius + sirius-components-view + 2024.1.2 + diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/EditingContext.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/EditingContext.java new file mode 100644 index 0000000000..6ebef30f0c --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/EditingContext.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2019, 2024 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.editingcontext; + +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.components.representations.IRepresentationDescription; +import org.eclipse.sirius.components.view.View; + +/** + * Implementation of the editing context. + * + * @author sbegaudeau + */ +public class EditingContext implements IEMFEditingContext { + + private final String id; + + private final AdapterFactoryEditingDomain editingDomain; + + private final Map representationDescriptions; + + private final List views; + + public EditingContext(String id, AdapterFactoryEditingDomain editingDomain, Map representationDescriptions, List views) { + this.id = Objects.requireNonNull(id); + this.editingDomain = Objects.requireNonNull(editingDomain); + this.representationDescriptions = Objects.requireNonNull(representationDescriptions); + this.views = Objects.requireNonNull(views); + } + + @Override + public String getId() { + return this.id; + } + + @Override + public AdapterFactoryEditingDomain getDomain() { + return this.editingDomain; + } + + public Map getRepresentationDescriptions() { + return this.representationDescriptions; + } + + public List getViews() { + return this.views; + } + +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/DomainSearchService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/DomainSearchService.java new file mode 100644 index 0000000000..1b56879078 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/DomainSearchService.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2024 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.editingcontext.services; + +import java.util.List; +import java.util.Optional; + +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.edit.domain.EditingDomain; +import org.eclipse.sirius.components.core.api.Domain; +import org.eclipse.sirius.components.core.api.IDomainSearchService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.springframework.stereotype.Service; + +/** + * Service used to search the domains available. + * + * @author frouene + */ +@Service +public class DomainSearchService implements IDomainSearchService { + @Override + public List findAllByEditingContext(IEditingContext editingContext) { + return Optional.of(editingContext) + .filter(IEMFEditingContext.class::isInstance) + .map(IEMFEditingContext.class::cast) + .map(IEMFEditingContext::getDomain) + .map(EditingDomain::getResourceSet) + .map(ResourceSet::getPackageRegistry) + .map(EPackage.Registry::values) + .orElse(List.of()) + .stream() + .filter(EPackage.class::isInstance) + .map(EPackage.class::cast) + .map(ePackage -> new Domain(ePackage.getNsURI(), ePackage.getNsURI())) + .sorted() + .toList(); + } + + @Override + public List findRootDomainsByEditingContext(IEditingContext editingContext) { + return Optional.of(editingContext) + .filter(IEMFEditingContext.class::isInstance) + .map(IEMFEditingContext.class::cast) + .map(IEMFEditingContext::getDomain) + .map(EditingDomain::getResourceSet) + .map(ResourceSet::getPackageRegistry) + .map(EPackage.Registry::values) + .orElse(List.of()) + .stream() + .filter(EPackage.class::isInstance) + .map(EPackage.class::cast) + .map(ePackage -> new Domain(ePackage.getNsURI(), ePackage.getNsURI())) + .sorted() + .toList(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextEPackageService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextEPackageService.java new file mode 100644 index 0000000000..a7b46bbf51 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextEPackageService.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2024 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.editingcontext.services; + +import java.util.List; + +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.sirius.components.emf.services.IEditingContextEPackageService; +import org.springframework.stereotype.Service; + +/** + * A service used to retrieve all the EPackages accessible for a given editing context. + * + * @author sbegaudeau + */ +@Service +public class EditingContextEPackageService implements IEditingContextEPackageService { + @Override + public List getEPackages(String editingContextId) { + return List.of(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextPersistenceService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextPersistenceService.java new file mode 100644 index 0000000000..605dfa68ae --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextPersistenceService.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) 2024 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.editingcontext.services; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IEditingContextPersistenceService; +import org.eclipse.sirius.components.emf.ResourceMetadataAdapter; +import org.eclipse.sirius.components.emf.services.EObjectIDManager; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; +import org.eclipse.sirius.emfjson.resource.JsonResource; +import org.eclipse.sirius.web.application.UUIDParser; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.Document; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataUpdateService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; + +/** + * Used to save the editing context. + * + * @author sbegaudeau + */ +@Service +public class EditingContextPersistenceService implements IEditingContextPersistenceService { + + private static final String TIMER_NAME = "siriusweb_editingcontext_save"; + + private final ISemanticDataUpdateService semanticDataUpdateService; + + private final Timer timer; + + private final Logger logger = LoggerFactory.getLogger(EditingContextPersistenceService.class); + + public EditingContextPersistenceService(ISemanticDataUpdateService semanticDataUpdateService, MeterRegistry meterRegistry) { + this.semanticDataUpdateService = Objects.requireNonNull(semanticDataUpdateService); + this.timer = Timer.builder(TIMER_NAME).register(meterRegistry); + } + + @Override + public void persist(IEditingContext editingContext) { + long start = System.currentTimeMillis(); + + if (editingContext instanceof IEMFEditingContext emfEditingContext) { + new UUIDParser().parse(editingContext.getId()) + .map(AggregateReference::to) + .ifPresent(project -> { + var documents = emfEditingContext.getDomain().getResourceSet().getResources().stream() + .map(this::toDocument) + .flatMap(Optional::stream) + .collect(Collectors.toSet()); + this.semanticDataUpdateService.updateDocuments(project, documents); + }); + } + + long end = System.currentTimeMillis(); + this.timer.record(end - start, TimeUnit.MILLISECONDS); + } + + private Optional toDocument(Resource resource) { + HashMap options = new HashMap<>(); + options.put(JsonResource.OPTION_ID_MANAGER, new EObjectIDManager()); + options.put(JsonResource.OPTION_SCHEMA_LOCATION, true); + + Optional optionalDocument = Optional.empty(); + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + resource.save(outputStream, options); + + for (Resource.Diagnostic warning : resource.getWarnings()) { + this.logger.warn(warning.getMessage()); + } + for (Resource.Diagnostic error : resource.getErrors()) { + this.logger.warn(error.getMessage()); + } + + var name = resource.eAdapters().stream() + .filter(ResourceMetadataAdapter.class::isInstance) + .map(ResourceMetadataAdapter.class::cast) + .findFirst().map(ResourceMetadataAdapter::getName) + .orElse(""); + var content = outputStream.toString(); + + var resourceId = resource.getURI().path().substring(1); + var documentId = new UUIDParser().parse(resourceId).orElse(UUID.randomUUID()); + + var document = Document.newDocument(documentId) + .name(name) + .content(content) + .build(); + optionalDocument = Optional.of(document); + } catch (IllegalArgumentException | IOException exception) { + this.logger.warn(exception.getMessage(), exception); + } + return optionalDocument; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextSearchService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextSearchService.java new file mode 100644 index 0000000000..959afeb1e3 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingContextSearchService.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2024 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.editingcontext.services; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IEditingContextProcessor; +import org.eclipse.sirius.components.core.api.IEditingContextRepresentationDescriptionProvider; +import org.eclipse.sirius.components.core.api.IEditingContextSearchService; +import org.eclipse.sirius.components.emf.ResourceMetadataAdapter; +import org.eclipse.sirius.components.emf.services.EditingContextCrossReferenceAdapter; +import org.eclipse.sirius.components.emf.services.JSONResourceFactory; +import org.eclipse.sirius.emfjson.resource.JsonResource; +import org.eclipse.sirius.web.application.UUIDParser; +import org.eclipse.sirius.web.application.editingcontext.EditingContext; +import org.eclipse.sirius.web.application.editingcontext.services.api.IEditingDomainFactory; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.project.services.api.IProjectSearchService; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataSearchService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Timer; + +/** + * Service used to find and retrieve editing contexts. + * + * @author sbegaudeau + */ +@Service +public class EditingContextSearchService implements IEditingContextSearchService { + + private static final String TIMER_NAME = "siriusweb_editingcontext_load"; + + private final Logger logger = LoggerFactory.getLogger(EditingContextSearchService.class); + + private final IProjectSearchService projectSearchService; + + private final ISemanticDataSearchService semanticDataSearchService; + + private final IEditingDomainFactory editingDomainFactory; + + private final List representationDescriptionProviders; + + private final List editingContextProcessors; + + private final Timer timer; + + public EditingContextSearchService(IProjectSearchService projectSearchService, ISemanticDataSearchService semanticDataSearchService, IEditingDomainFactory editingDomainFactory, + List representationDescriptionProviders, List editingContextProcessors, MeterRegistry meterRegistry) { + this.projectSearchService = Objects.requireNonNull(projectSearchService); + this.semanticDataSearchService = Objects.requireNonNull(semanticDataSearchService); + this.editingDomainFactory = Objects.requireNonNull(editingDomainFactory); + this.representationDescriptionProviders = Objects.requireNonNull(representationDescriptionProviders); + this.editingContextProcessors = Objects.requireNonNull(editingContextProcessors); + this.timer = Timer.builder(TIMER_NAME).register(meterRegistry); + } + + @Override + public boolean existsById(String editingContextId) { + return new UUIDParser().parse(editingContextId) + .map(AggregateReference::to) + .map(this.semanticDataSearchService::existsByProject) + .orElse(false); + } + + @Override + public Optional findById(String editingContextId) { + return new UUIDParser().parse(editingContextId) + .flatMap(this.projectSearchService::findById) + .map(this::toEditingContext); + } + + private IEditingContext toEditingContext(Project project) { + long start = System.currentTimeMillis(); + + this.logger.debug("Loading the editing context {}", project.getId()); + + AdapterFactoryEditingDomain editingDomain = this.editingDomainFactory.createEditingDomain(project); + EditingContext editingContext = new EditingContext(project.getId().toString(), editingDomain, new HashMap<>(), new ArrayList<>()); + this.editingContextProcessors.forEach(processor -> processor.preProcess(editingContext)); + + this.semanticDataSearchService.findByProject(AggregateReference.to(project.getId())) + .ifPresent(semanticData -> this.loadSemanticData(editingContext, semanticData)); + + this.representationDescriptionProviders.forEach(representationDescriptionProvider -> { + var representationDescriptions = representationDescriptionProvider.getRepresentationDescriptions(editingContext); + representationDescriptions.forEach(representationDescription -> editingContext.getRepresentationDescriptions().put(representationDescription.getId(), representationDescription)); + }); + + this.editingContextProcessors.forEach(processor -> processor.postProcess(editingContext)); + + long end = System.currentTimeMillis(); + this.timer.record(end - start, TimeUnit.MILLISECONDS); + + return editingContext; + } + + private void loadSemanticData(EditingContext editingContext, SemanticData semanticData) { + ResourceSet resourceSet = editingContext.getDomain().getResourceSet(); + resourceSet.getLoadOptions().put(JsonResource.OPTION_SCHEMA_LOCATION, true); + + var documents = semanticData.getDocuments(); + for (var document : documents) { + var resource = new JSONResourceFactory().createResourceFromPath(document.getId().toString()); + + try (var inputStream = new ByteArrayInputStream(document.getContent().getBytes())) { + resourceSet.getResources().add(resource); + resource.load(inputStream, null); + + resource.eAdapters().add(new ResourceMetadataAdapter(document.getName())); + } catch (IOException | IllegalArgumentException exception) { + this.logger.warn("An error occured while loading document {}: {}.", document.getId(), exception.getMessage()); + resourceSet.getResources().remove(resource); + } + } + + // The ECrossReferenceAdapter must be set after the resource loading because it needs to resolve proxies in case + // of inter-resources references + resourceSet.eAdapters().add(new EditingContextCrossReferenceAdapter()); + + this.logger.debug("{} documents loaded for the editing context {}", resourceSet.getResources().size(), editingContext.getId()); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingDomainFactory.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingDomainFactory.java new file mode 100644 index 0000000000..eb90ad2302 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/EditingDomainFactory.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2023, 2024 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.editingcontext.services; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +import org.eclipse.emf.common.command.BasicCommandStack; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.impl.EPackageRegistryImpl; +import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.emf.ecore.util.BasicExtendedMetaData; +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.sirius.components.emf.services.IEditingContextEPackageService; +import org.eclipse.sirius.emfjson.resource.JsonResource; +import org.eclipse.sirius.web.application.editingcontext.services.api.IEditingDomainFactory; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +/** + * This class is used to create the editing domain used of the editing context. + * It instantiates the ResourceSet with the right configuration. + * + * @author lfasani + */ +@Service +public class EditingDomainFactory implements IEditingDomainFactory { + + private final Logger logger = LoggerFactory.getLogger(EditingDomainFactory.class); + + private final IEditingContextEPackageService editingContextEPackageService; + + private final ComposedAdapterFactory composedAdapterFactory; + + private final EPackage.Registry globalEPackageRegistry; + + public EditingDomainFactory(IEditingContextEPackageService editingContextEPackageService, ComposedAdapterFactory composedAdapterFactory, EPackage.Registry globalEPackageRegistry) { + this.editingContextEPackageService = Objects.requireNonNull(editingContextEPackageService); + this.composedAdapterFactory = Objects.requireNonNull(composedAdapterFactory); + this.globalEPackageRegistry = Objects.requireNonNull(globalEPackageRegistry); + } + + @Override + public AdapterFactoryEditingDomain createEditingDomain(Project project) { + AdapterFactoryEditingDomain editingDomain = new AdapterFactoryEditingDomain(this.composedAdapterFactory, new BasicCommandStack()); + ResourceSet resourceSet = editingDomain.getResourceSet(); + resourceSet.getLoadOptions().put(JsonResource.OPTION_EXTENDED_META_DATA, new BasicExtendedMetaData(resourceSet.getPackageRegistry())); + resourceSet.getLoadOptions().put(JsonResource.OPTION_SCHEMA_LOCATION, true); + + EPackageRegistryImpl ePackageRegistry = new EPackageRegistryImpl(); + List additionalEPackages = this.editingContextEPackageService.getEPackages(project.getId().toString()); + + Stream.concat(this.findGlobalEPackages(), additionalEPackages.stream()) + .forEach(ePackage -> ePackageRegistry.put(ePackage.getNsURI(), ePackage)); + resourceSet.setPackageRegistry(ePackageRegistry); + + return editingDomain; + } + + private Stream findGlobalEPackages() { + return this.globalEPackageRegistry.values().stream() + .filter(EPackage.class::isInstance) + .map(EPackage.class::cast); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/api/IEditingDomainFactory.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/api/IEditingDomainFactory.java new file mode 100644 index 0000000000..77923c4444 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/editingcontext/services/api/IEditingDomainFactory.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2023, 2024 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.editingcontext.services.api; + +import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; + +/** + * Service used to create the editing domain used in the editing context. + * + * @author frouene + */ +public interface IEditingDomainFactory { + + AdapterFactoryEditingDomain createEditingDomain(Project project); + + /** + * Implementation which does nothing, used for mocks in unit tests. + * + * @author frouene + */ + class NoOp implements IEditingDomainFactory { + + @Override + public AdapterFactoryEditingDomain createEditingDomain(Project project) { + return null; + } + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/DanglingRepresentationDeletionService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/DanglingRepresentationDeletionService.java new file mode 100644 index 0000000000..53a2b5d432 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/DanglingRepresentationDeletionService.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representation.services; + +import org.eclipse.sirius.components.collaborative.api.IDanglingRepresentationDeletionService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.representations.IRepresentation; +import org.springframework.stereotype.Service; + +/** + * Used to delete dangling representations. + * + * @author sbegaudeau + */ +@Service +public class DanglingRepresentationDeletionService implements IDanglingRepresentationDeletionService { + @Override + public boolean isDangling(IEditingContext editingContext, IRepresentation representation) { + return false; + } + + @Override + public void deleteDanglingRepresentations(String editingContextId) { + // Do nothing for now + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationDescriptionSearchService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationDescriptionSearchService.java new file mode 100644 index 0000000000..6ad063ccde --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationDescriptionSearchService.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representation.services; + +import java.util.Map; +import java.util.Optional; + +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService; +import org.eclipse.sirius.components.representations.IRepresentationDescription; +import org.eclipse.sirius.web.application.editingcontext.EditingContext; +import org.springframework.stereotype.Service; + +/** + * Service used to search the representation descriptions available. + * + * @author sbegaudeau + * @author hmarchadour + */ +@Service +public class RepresentationDescriptionSearchService implements IRepresentationDescriptionSearchService { + + @Override + public Map findAll(IEditingContext editingContext) { + return Optional.of(editingContext) + .filter(EditingContext.class::isInstance) + .map(EditingContext.class::cast) + .map(EditingContext::getRepresentationDescriptions) + .orElse(Map.of()); + } + + @Override + public Optional findById(IEditingContext editingContext, String representationDescriptionId) { + return Optional.of(editingContext) + .filter(EditingContext.class::isInstance) + .map(EditingContext.class::cast) + .map(EditingContext::getRepresentationDescriptions) + .map(representationDescriptions -> representationDescriptions.get(representationDescriptionId)); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationMetadataSearchService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationMetadataSearchService.java new file mode 100644 index 0000000000..09551ef426 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationMetadataSearchService.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representation.services; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.core.RepresentationMetadata; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IRepresentationMetadataSearchService; +import org.eclipse.sirius.components.representations.IRepresentation; +import org.eclipse.sirius.web.application.UUIDParser; +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.services.api.IRepresentationDataSearchService; +import org.springframework.stereotype.Service; + +/** + * Used to find the metadata of a representation. + * + * @author sbegaudeau + */ +@Service +public class RepresentationMetadataSearchService implements IRepresentationMetadataSearchService { + + private final IRepresentationDataSearchService representationDataSearchService; + + public RepresentationMetadataSearchService(IRepresentationDataSearchService representationDataSearchService) { + this.representationDataSearchService = Objects.requireNonNull(representationDataSearchService); + } + + @Override + public Optional findByRepresentationId(String representationId) { + return new UUIDParser().parse(representationId) + .flatMap(this.representationDataSearchService::findById) + .map(representation -> new RepresentationMetadata(representation.getId().toString(), representation.getKind(), representation.getLabel(), representation.getDescriptionId())); + } + + @Override + public Optional findByRepresentation(IRepresentation representation) { + return Optional.of(new RepresentationMetadata(representation.getId(), representation.getKind(), representation.getLabel(), representation.getDescriptionId())); + } + + @Override + public List findAllByTargetObjectId(IEditingContext editingContext, String targetObjectId) { + return this.representationDataSearchService.findAllByTargetObjectId(targetObjectId) + .stream() + .map(representation -> new RepresentationMetadata(representation.getId().toString(), representation.getKind(), representation.getLabel(), representation.getDescriptionId())) + .toList(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationPersistenceService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationPersistenceService.java new file mode 100644 index 0000000000..0d4042a67a --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationPersistenceService.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representation.services; + +import org.eclipse.sirius.components.collaborative.api.IRepresentationPersistenceService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.representations.ISemanticRepresentation; +import org.springframework.stereotype.Service; + +/** + * Used to persist representations. + * + * @author sbegaudeau + */ +@Service +public class RepresentationPersistenceService implements IRepresentationPersistenceService { + @Override + public void save(IEditingContext editingContext, ISemanticRepresentation representation) { + // Do nothing for now + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationSearchService.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationSearchService.java new file mode 100644 index 0000000000..b22022d6a0 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/representation/services/RepresentationSearchService.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representation.services; + +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.IRepresentationSearchService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.representations.IRepresentation; +import org.springframework.stereotype.Service; + +/** + * Used to find representations. + * + * @author sbegaudeau + */ +@Service +public class RepresentationSearchService implements IRepresentationSearchService { + + @Override + public Optional findById(IEditingContext editingContext, String representationId, Class representationClass) { + return Optional.empty(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/semanticdata/listeners/SemanticDataInitializer.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/semanticdata/listeners/SemanticDataInitializer.java new file mode 100644 index 0000000000..c97455806e --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/semanticdata/listeners/SemanticDataInitializer.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2024 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.semanticdata.listeners; + +import java.util.Objects; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.events.ProjectCreatedEvent; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataCreationService; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.event.TransactionalEventListener; + +/** + * Service used to create the semantic data of a project. + * + * @author sbegaudeau + */ +@Service +public class SemanticDataInitializer { + + private final ISemanticDataCreationService semanticDataCreationService; + + public SemanticDataInitializer(ISemanticDataCreationService semanticDataCreationService) { + this.semanticDataCreationService = Objects.requireNonNull(semanticDataCreationService); + } + + @Transactional + @TransactionalEventListener + public void onProjectCreatedEvent(ProjectCreatedEvent event) { + this.semanticDataCreationService.create(AggregateReference.to(event.project().getId())); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/DefaultViewer.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/DefaultViewer.java new file mode 100644 index 0000000000..a84f36e175 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/DefaultViewer.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2024 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.viewer; + +/** + * The viewer DTO. + * + * @author sbegaudeau + */ +public record DefaultViewer() implements IViewer { +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/IViewer.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/IViewer.java new file mode 100644 index 0000000000..c6ac3a1322 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/IViewer.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2024 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.viewer; + +/** + * Interface used to represent a viewer. + * + * @author gcoutable + */ +public interface IViewer { +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/controllers/QueryViewDataFetcher.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/controllers/QueryViewDataFetcher.java new file mode 100644 index 0000000000..d4cba7958d --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/viewer/controllers/QueryViewDataFetcher.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2024 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.viewer.controllers; + +import org.eclipse.sirius.components.annotations.spring.graphql.QueryDataFetcher; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.web.application.viewer.IViewer; +import org.eclipse.sirius.web.application.viewer.DefaultViewer; + +import graphql.schema.DataFetchingEnvironment; + +/** + * Data fetcher for the field Query#viewer. + * + * @author sbegaudeau + */ +@QueryDataFetcher(type = "Query", field = "viewer") +public class QueryViewDataFetcher implements IDataFetcherWithFieldCoordinates { + @Override + public IViewer get(DataFetchingEnvironment environment) throws Exception { + return new DefaultViewer(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/.gitkeep b/packages/sirius-web/backend/sirius-web-application/src/main/resources/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls b/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls new file mode 100644 index 0000000000..11bcf66409 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/schema/siriusweb.graphqls @@ -0,0 +1,43 @@ +extend interface Viewer { + project(projectId: ID!): Project + projects(page: Int!, limit: Int!): ViewerProjectConnection! +} + +type ViewerProjectConnection { + edges: [ViewerProjectEdge!]! + pageInfo: PageInfo! +} + +type ViewerProjectEdge { + node: Project! +} + +type Project { + id: ID! + name: String! +} + +type DefaultViewer implements Viewer { + id: ID! + username: String! + editingContext(editingContextId: ID!): EditingContext + project(projectId: ID!): Project + projects(page: Int!, limit: Int!): ViewerProjectConnection! +} + +extend type Mutation { + createProject(input: CreateProjectInput!): CreateProjectPayload! +} + +input CreateProjectInput { + id: ID! + name: String! + natures: [String!]! +} + +union CreateProjectPayload = ErrorPayload | CreateProjectSuccessPayload + +type CreateProjectSuccessPayload { + id: ID! + project: Project! +} \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/ProjectSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/ProjectSearchService.java index b86920af21..4eccfb909b 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/ProjectSearchService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/ProjectSearchService.java @@ -38,8 +38,13 @@ public ProjectSearchService(IProjectRepository projectRepository) { } @Override - public Optional findById(UUID id) { - return this.projectRepository.findById(id); + public boolean existsById(UUID projectId) { + return this.projectRepository.existsById(projectId); + } + + @Override + public Optional findById(UUID projectId) { + return this.projectRepository.findById(projectId); } @Override diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/api/IProjectSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/api/IProjectSearchService.java index bedea6ac15..37b8057aae 100644 --- a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/api/IProjectSearchService.java +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/project/services/api/IProjectSearchService.java @@ -25,7 +25,10 @@ * @author sbegaudeau */ public interface IProjectSearchService { - Optional findById(UUID id); + + boolean existsById(UUID projectId); + + Optional findById(UUID projectId); Page findAll(Pageable pageable); } diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/RepresentationData.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/RepresentationData.java new file mode 100644 index 0000000000..acddca35dd --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/RepresentationData.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata; + +import java.time.Instant; +import java.util.Objects; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.AbstractValidatingAggregateRoot; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.events.RepresentationDataCreatedEvent; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.domain.Persistable; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.Table; + +/** + * The aggregate root of the representation data bounded context. + * + * @author sbegaudeau + */ +@Table("representation_data") +public class RepresentationData extends AbstractValidatingAggregateRoot implements Persistable { + @Transient + private boolean isNew; + + @Id + private UUID id; + + @Column("project_id") + private AggregateReference project; + + private String targetObjectId; + + private String descriptionId; + + private String label; + + private String kind; + + private String content; + + private Instant createdOn; + + private Instant lastModifiedOn; + + @Override + public UUID getId() { + return this.id; + } + + public AggregateReference getProject() { + return this.project; + } + + public String getTargetObjectId() { + return this.targetObjectId; + } + + public String getDescriptionId() { + return this.descriptionId; + } + + public String getLabel() { + return this.label; + } + + public String getKind() { + return this.kind; + } + + public String getContent() { + return this.content; + } + + public Instant getCreatedOn() { + return this.createdOn; + } + + public Instant getLastModifiedOn() { + return this.lastModifiedOn; + } + + @Override + public boolean isNew() { + return this.isNew; + } + + public static Builder newRepresentationData() { + return new Builder(); + } + + /** + * Used to create new representation data. + * + * @author sbegaudeau + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + private AggregateReference project; + + private String targetObjectId; + + private String descriptionId; + + private String label; + + private String kind; + + private String content; + + public Builder targetObjectId(String targetObjectId) { + this.targetObjectId = Objects.requireNonNull(targetObjectId); + return this; + } + + public Builder descriptionId(String descriptionId) { + this.descriptionId = Objects.requireNonNull(descriptionId); + return this; + } + + public Builder label(String label) { + this.label = Objects.requireNonNull(label); + return this; + } + + public Builder kind(String kind) { + this.kind = Objects.requireNonNull(kind); + return this; + } + + public Builder content(String content) { + this.content = Objects.requireNonNull(content); + return this; + } + + public RepresentationData build() { + var representationData = new RepresentationData(); + representationData.isNew = true; + representationData.id = UUID.randomUUID(); + representationData.project = Objects.requireNonNull(this.project); + representationData.targetObjectId = Objects.requireNonNull(this.targetObjectId); + representationData.descriptionId = Objects.requireNonNull(this.descriptionId); + representationData.label = Objects.requireNonNull(this.label); + representationData.kind = Objects.requireNonNull(this.kind); + representationData.content = Objects.requireNonNull(this.content); + + var now = Instant.now(); + representationData.createdOn = now; + representationData.lastModifiedOn = now; + + representationData.registerEvent(new RepresentationDataCreatedEvent(UUID.randomUUID(), now, representationData)); + return representationData; + } + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/IRepresentationDataEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/IRepresentationDataEvent.java new file mode 100644 index 0000000000..e7b4bedac4 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/IRepresentationDataEvent.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.events; + +import org.eclipse.sirius.web.domain.events.IDomainEvent; + +/** + * Interface implemented by all the domain events of the representation data bounded context. + * + * @author sbegaudeau + */ +public interface IRepresentationDataEvent extends IDomainEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataCreatedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataCreatedEvent.java new file mode 100644 index 0000000000..09a942dbbf --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataCreatedEvent.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.events; + +import java.time.Instant; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationData; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when some representation data are created. + * + * @author sbegaudeau + */ +public record RepresentationDataCreatedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull RepresentationData representationData) implements IRepresentationDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataUpdatedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataUpdatedEvent.java new file mode 100644 index 0000000000..5c9d54da43 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/events/RepresentationDataUpdatedEvent.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.events; + +import java.time.Instant; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationData; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when some representation data are updated. + * + * @author sbegaudeau + */ +public record RepresentationDataUpdatedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull RepresentationData representationData) implements IRepresentationDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/repositories/IRepresentationDataRepository.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/repositories/IRepresentationDataRepository.java new file mode 100644 index 0000000000..a10795b9fe --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/repositories/IRepresentationDataRepository.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2024, 2024 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.representationdata.repositories; + +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationData; +import org.springframework.data.repository.ListCrudRepository; +import org.springframework.data.repository.ListPagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +/** + * Repository used to persist the representation data aggregate. + * + * @author sbegaudeau + */ +@Repository +public interface IRepresentationDataRepository extends ListPagingAndSortingRepository, ListCrudRepository { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataCreationService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataCreationService.java new file mode 100644 index 0000000000..a4760efa13 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataCreationService.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2024, 2024 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.representationdata.services; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.services.api.IRepresentationDataCreationService; +import org.springframework.stereotype.Service; + +/** + * Used to create new representation data. + * + * @author sbegaudeau + */ +@Service +public class RepresentationDataCreationService implements IRepresentationDataCreationService { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataSearchService.java new file mode 100644 index 0000000000..bae4d7f406 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/RepresentationDataSearchService.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.services; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationData; +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.services.api.IRepresentationDataSearchService; +import org.springframework.stereotype.Service; + +/** + * Used to find representation data. + * + * @author sbegaudeau + */ +@Service +public class RepresentationDataSearchService implements IRepresentationDataSearchService { + @Override + public Optional findById(UUID id) { + return Optional.empty(); + } + + @Override + public List findAllByTargetObjectId(String targetObjectId) { + return List.of(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataCreationService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataCreationService.java new file mode 100644 index 0000000000..9daa8f494e --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataCreationService.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.services.api; + +/** + * Used to create new representation data. + * + * @author sbegaudeau + */ +public interface IRepresentationDataCreationService { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataSearchService.java new file mode 100644 index 0000000000..bc9dbc6d21 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/representationdata/services/api/IRepresentationDataSearchService.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2024 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.representationdata.services.api; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationData; + +/** + * Used to find representation data. + * + * @author sbegaudeau + */ +public interface IRepresentationDataSearchService { + Optional findById(UUID id); + + List findAllByTargetObjectId(String targetObjectId); +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/Document.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/Document.java new file mode 100644 index 0000000000..7bc944d866 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/Document.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2024 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.time.Instant; +import java.util.Objects; +import java.util.UUID; + +import org.springframework.data.relational.core.mapping.Table; + +/** + * The document entity of the semantic data aggregate. + * + * @author sbegaudeau + */ +@Table("document") +public class Document { + + private UUID id; + + private String name; + + private String content; + + private Instant createdOn; + + private Instant lastModifiedOn; + + public UUID getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public String getContent() { + return this.content; + } + + public Instant getCreatedOn() { + return this.createdOn; + } + + public Instant getLastModifiedOn() { + return this.lastModifiedOn; + } + + public static Builder newDocument(UUID id) { + return new Builder(id); + } + + /** + * Used to create new documents. + * + * @author sbegaudeau + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + + private UUID id; + + private String name; + + private String content; + + private Builder(UUID id) { + this.id = Objects.requireNonNull(id); + } + + public Builder name(String name) { + this.name = Objects.requireNonNull(name); + return this; + } + + public Builder content(String content) { + this.content = Objects.requireNonNull(content); + return this; + } + + public Document build() { + var document = new Document(); + document.id = Objects.requireNonNull(this.id); + document.name = Objects.requireNonNull(this.name); + document.content = Objects.requireNonNull(this.content); + + var now = Instant.now(); + document.createdOn = now; + document.lastModifiedOn = now; + + return document; + } + } +} 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 new file mode 100644 index 0000000000..a03828271c --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/SemanticData.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2024 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.time.Instant; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.AbstractValidatingAggregateRoot; +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataCreatedEvent; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.events.SemanticDataUpdatedEvent; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.domain.Persistable; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.data.relational.core.mapping.Column; +import org.springframework.data.relational.core.mapping.MappedCollection; +import org.springframework.data.relational.core.mapping.Table; + +/** + * The aggregate root of the semantic data bounded context. + * + * @author sbegaudeau + */ +@Table("semantic_data") +public class SemanticData extends AbstractValidatingAggregateRoot implements Persistable { + + @Transient + private boolean isNew; + + @Id + private UUID id; + + @Column("project_id") + private AggregateReference project; + + @MappedCollection(idColumn = "semantic_data_id") + private Set documents = new LinkedHashSet<>(); + + private Instant createdOn; + + private Instant lastModifiedOn; + + @Override + public UUID getId() { + return this.id; + } + + public AggregateReference getProject() { + return this.project; + } + + public Set getDocuments() { + return Collections.unmodifiableSet(this.documents); + } + + public Instant getCreatedOn() { + return this.createdOn; + } + + public Instant getLastModifiedOn() { + return this.lastModifiedOn; + } + + @Override + public boolean isNew() { + return this.isNew; + } + + public void updateDocuments(Set newDocuments) { + this.documents = newDocuments; + + this.lastModifiedOn = Instant.now(); + this.registerEvent(new SemanticDataUpdatedEvent(UUID.randomUUID(), this.lastModifiedOn, this)); + } + + public static Builder newSemanticData() { + return new Builder(); + } + + /** + * Used to create new semantic data. + * + * @author sbegaudeau + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + private AggregateReference project; + + private Set documents = new LinkedHashSet<>(); + + public Builder project(AggregateReference project) { + this.project = Objects.requireNonNull(project); + return this; + } + + public Builder documents(Set documents) { + this.documents = Objects.requireNonNull(documents); + return this; + } + + public SemanticData build() { + var semanticData = new SemanticData(); + + semanticData.isNew = true; + semanticData.id = UUID.randomUUID(); + semanticData.project = Objects.requireNonNull(project); + semanticData.documents = Objects.requireNonNull(this.documents); + + var now = Instant.now(); + semanticData.createdOn = now; + semanticData.lastModifiedOn = now; + + semanticData.registerEvent(new SemanticDataCreatedEvent(UUID.randomUUID(), now, semanticData)); + return semanticData; + } + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/ISemanticDataEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/ISemanticDataEvent.java new file mode 100644 index 0000000000..384bb1f0ba --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/ISemanticDataEvent.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2024 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 org.eclipse.sirius.web.domain.events.IDomainEvent; + +/** + * Interface implemented by all the domain events of the semantic data bounded context. + * + * @author sbegaudeau + */ +public interface ISemanticDataEvent extends IDomainEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataCreatedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataCreatedEvent.java new file mode 100644 index 0000000000..9ee9d49fc4 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataCreatedEvent.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 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.web.domain.boundedcontexts.semanticdata.SemanticData; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when the semantic data are created. + * + * @author sbegaudeau + */ +public record SemanticDataCreatedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull SemanticData semanticData) implements ISemanticDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataUpdatedEvent.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataUpdatedEvent.java new file mode 100644 index 0000000000..7c52771792 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/events/SemanticDataUpdatedEvent.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2024 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.web.domain.boundedcontexts.semanticdata.SemanticData; + +import jakarta.validation.constraints.NotNull; + +/** + * Event fired when the semantic data are updated. + * + * @author sbegaudeau + */ +public record SemanticDataUpdatedEvent( + @NotNull UUID id, + @NotNull Instant createdOn, + @NotNull SemanticData semanticData) implements ISemanticDataEvent { +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/repositories/ISemanticDataRepository.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/repositories/ISemanticDataRepository.java new file mode 100644 index 0000000000..042d42a9c6 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/repositories/ISemanticDataRepository.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2024 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.repositories; + +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.springframework.data.jdbc.repository.query.Query; +import org.springframework.data.repository.ListCrudRepository; +import org.springframework.data.repository.ListPagingAndSortingRepository; +import org.springframework.stereotype.Repository; + +/** + * Repository used to persist the semantic data aggregate. + * + * @author sbegaudeau + */ +@Repository +public interface ISemanticDataRepository extends ListPagingAndSortingRepository, ListCrudRepository { + @Query(""" + SELECT + CASE WHEN count(*)> 0 THEN true ELSE false END + FROM semantic_data semanticData + WHERE semanticData.project_id = :projectId + """) + boolean existsByProjectId(UUID projectId); + + @Query(""" + SELECT * + FROM semantic_data semanticData + WHERE semanticData.project_id = :projectId + """) + Optional findByProjectId(UUID projectId); +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataCreationService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataCreationService.java new file mode 100644 index 0000000000..e7e67688ca --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataCreationService.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services; + +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +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.ISemanticDataCreationService; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; + +/** + * Used to create semantic data. + * + * @author sbegaudeau + */ +@Service +public class SemanticDataCreationService implements ISemanticDataCreationService { + + private final ISemanticDataRepository semanticDataRepository; + + public SemanticDataCreationService(ISemanticDataRepository semanticDataRepository) { + this.semanticDataRepository = Objects.requireNonNull(semanticDataRepository); + } + + @Override + public void create(AggregateReference project) { + var semanticData = SemanticData.newSemanticData() + .project(project) + .documents(Set.of()) + .build(); + this.semanticDataRepository.save(semanticData); + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataSearchService.java new file mode 100644 index 0000000000..e44125ad0a --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataSearchService.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +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.ISemanticDataSearchService; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; + +/** + * Used to retrieve semantic data. + * + * @author sbegaudeau + */ +@Service +public class SemanticDataSearchService implements ISemanticDataSearchService { + + private final ISemanticDataRepository semanticDataRepository; + + public SemanticDataSearchService(ISemanticDataRepository semanticDataRepository) { + this.semanticDataRepository = Objects.requireNonNull(semanticDataRepository); + } + + @Override + public boolean existsByProject(AggregateReference project) { + return this.semanticDataRepository.existsByProjectId(project.getId()); + } + + @Override + public Optional findByProject(AggregateReference project) { + return this.semanticDataRepository.findByProjectId(project.getId()); + } +} 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 new file mode 100644 index 0000000000..a033070b90 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/SemanticDataUpdateService.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services; + +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.Document; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.repositories.ISemanticDataRepository; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.services.api.ISemanticDataUpdateService; +import org.springframework.data.jdbc.core.mapping.AggregateReference; +import org.springframework.stereotype.Service; + +/** + * Used to update the semantic data. + * + * @author sbegaudeau + */ +@Service +public class SemanticDataUpdateService implements ISemanticDataUpdateService { + + private final ISemanticDataRepository semanticDataRepository; + + public SemanticDataUpdateService(ISemanticDataRepository semanticDataRepository) { + this.semanticDataRepository = Objects.requireNonNull(semanticDataRepository); + } + + @Override + public void updateDocuments(AggregateReference project, Set documents) { + this.semanticDataRepository.findByProjectId(project.getId()).ifPresent(semanticData -> { + semanticData.updateDocuments(documents); + }); + } +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataCreationService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataCreationService.java new file mode 100644 index 0000000000..f4b3831ac1 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataCreationService.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services.api; + +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.springframework.data.jdbc.core.mapping.AggregateReference; + +/** + * Used to create the semantic data. + * + * @author sbegaudeau + */ +public interface ISemanticDataCreationService { + void create(AggregateReference project); +} diff --git a/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataSearchService.java b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataSearchService.java new file mode 100644 index 0000000000..1429373616 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataSearchService.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services.api; + +import java.util.Optional; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.SemanticData; +import org.springframework.data.jdbc.core.mapping.AggregateReference; + +/** + * Used to retrieve the semantic data. + * + * @author sbegaudeau + */ +public interface ISemanticDataSearchService { + + boolean existsByProject(AggregateReference project); + + Optional findByProject(AggregateReference project); +} 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 new file mode 100644 index 0000000000..291896f034 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-domain/src/main/java/org/eclipse/sirius/web/domain/boundedcontexts/semanticdata/services/api/ISemanticDataUpdateService.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2024 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.services.api; + +import java.util.Set; +import java.util.UUID; + +import org.eclipse.sirius.web.domain.boundedcontexts.project.Project; +import org.eclipse.sirius.web.domain.boundedcontexts.semanticdata.Document; +import org.springframework.data.jdbc.core.mapping.AggregateReference; + +/** + * Used to update the semantic data. + * + * @author sbegaudeau + */ +public interface ISemanticDataUpdateService { + void updateDocuments(AggregateReference project, Set documents); +} diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLConfiguration.java b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLConfiguration.java new file mode 100644 index 0000000000..7bcb3881fd --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLConfiguration.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2024 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.infrastructure.graphql; + +import java.io.IOException; +import java.util.List; + +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.InstantScalarType; +import org.eclipse.sirius.components.graphql.api.UploadScalarType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.ResourcePatternResolver; + +import graphql.GraphQL; +import graphql.execution.AsyncExecutionStrategy; +import graphql.execution.AsyncSerialExecutionStrategy; +import graphql.execution.DataFetcherExceptionHandler; +import graphql.execution.ExecutionStrategy; +import graphql.schema.GraphQLCodeRegistry; +import graphql.schema.GraphQLSchema; +import graphql.schema.idl.RuntimeWiring; +import graphql.schema.idl.SchemaGenerator; +import graphql.schema.idl.SchemaParser; +import graphql.schema.idl.SchemaPrinter; +import graphql.schema.idl.TypeDefinitionRegistry; + +/** + * Spring Configuration used to create everything necessary to run GraphQL queries. + *

+ * This class is responsible of the configuration of both the GraphQL schema and the code used to execute GraphQL + * queries. It will provide an instance of the {@link GraphQL} configuration object which can be injected as a bean in + * order components. + *

+ * + * @author sbegaudeau + */ +@Configuration +public class GraphQLConfiguration { + + private final Logger logger = LoggerFactory.getLogger(GraphQLConfiguration.class); + + @Bean + public GraphQL graphQL(GraphQLSchema graphQLSchema) { + var options = SchemaPrinter.Options.defaultOptions(); + String schema = new SchemaPrinter(options).print(graphQLSchema); + + this.logger.trace(schema); + + DataFetcherExceptionHandler exceptionHandler = new GraphQLDataFetcherExceptionHandler(); + ExecutionStrategy queryExecutionStrategy = new AsyncExecutionStrategy(exceptionHandler); + // @see https://www.graphql-java.com/documentation/v11/execution/ The graphql specification says that mutations + // MUST be executed serially and in the order in which the query fields occur. + ExecutionStrategy mutationExecutionStrategy = new AsyncSerialExecutionStrategy(exceptionHandler); + // @formatter:off + return GraphQL.newGraphQL(graphQLSchema) + .queryExecutionStrategy(queryExecutionStrategy) + .mutationExecutionStrategy(mutationExecutionStrategy) + .build(); + // @formatter:on + } + + @Bean + public GraphQLSchema graphQLSchema(ResourcePatternResolver resourcePatternResolver, GraphQLWiringFactory graphQLWiringFactory, List> dataFetchersWithCoordinates) { + GraphQLCodeRegistry.Builder builder = GraphQLCodeRegistry.newCodeRegistry(); + dataFetchersWithCoordinates.forEach(dataFetcherWithCoordinates -> { + dataFetcherWithCoordinates.getFieldCoordinates().forEach(fieldCoordinates -> builder.dataFetcher(fieldCoordinates, dataFetcherWithCoordinates)); + }); + var graphQLCodeRegistry = builder.build(); + + try { + TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry(); + + SchemaParser schemaParser = new SchemaParser(); + SchemaGenerator schemaGenerator = new SchemaGenerator(); + + Resource[] resources = resourcePatternResolver.getResources("classpath*:/schema/**/*.graphqls"); + this.logger.info("{} GraphQL schemas found", resources.length); + for (Resource resource : resources) { + if (this.logger.isInfoEnabled()) { + this.logger.info("Processing the GraphQL schema: {}", resource.getURL()); + } + TypeDefinitionRegistry childTypeDefinitionRegistry = schemaParser.parse(resource.getInputStream()); + typeRegistry.merge(childTypeDefinitionRegistry); + } + + var runtimeWiring = RuntimeWiring.newRuntimeWiring() + .codeRegistry(graphQLCodeRegistry) + .wiringFactory(graphQLWiringFactory) + .scalar(UploadScalarType.INSTANCE) + .scalar(InstantScalarType.INSTANCE) + .build(); + + return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring); + } catch (IOException exception) { + this.logger.warn(exception.getMessage(), exception); + } + return null; + } +} \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLDataFetcherExceptionHandler.java b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLDataFetcherExceptionHandler.java new file mode 100644 index 0000000000..62f6f56c3b --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLDataFetcherExceptionHandler.java @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2024 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.infrastructure.graphql; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import graphql.ExceptionWhileDataFetching; +import graphql.GraphQLError; +import graphql.execution.DataFetcherExceptionHandler; +import graphql.execution.DataFetcherExceptionHandlerParameters; +import graphql.execution.DataFetcherExceptionHandlerResult; + +/** + * Used to handle any exception coming from a data fetcher. + * + * @author sbegaudeau + */ +public class GraphQLDataFetcherExceptionHandler implements DataFetcherExceptionHandler { + + private final Logger logger = LoggerFactory.getLogger(GraphQLDataFetcherExceptionHandler.class); + + @Override + public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) { + this.logger.warn(handlerParameters.getException().getMessage(), handlerParameters.getException()); + + GraphQLError error = this.getGraphQLError(handlerParameters); + + return DataFetcherExceptionHandlerResult.newResult() + .error(error) + .build(); + } + + private GraphQLError getGraphQLError(DataFetcherExceptionHandlerParameters handlerParameters) { + return new ExceptionWhileDataFetching(handlerParameters.getPath(), handlerParameters.getException(), handlerParameters.getSourceLocation()); + } + +} \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLWiringFactory.java b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLWiringFactory.java new file mode 100644 index 0000000000..edad5f16e6 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/graphql/GraphQLWiringFactory.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2024 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.infrastructure.graphql; + +import org.eclipse.sirius.components.graphql.api.ReflectiveTypeResolver; +import org.springframework.stereotype.Service; + +import graphql.schema.TypeResolver; +import graphql.schema.idl.InterfaceWiringEnvironment; +import graphql.schema.idl.UnionWiringEnvironment; +import graphql.schema.idl.WiringFactory; + +/** + * Wire the type resolvers for the type definitions. + * + * @author sbegaudeau + */ +@Service +public class GraphQLWiringFactory implements WiringFactory { + + @Override + public boolean providesTypeResolver(InterfaceWiringEnvironment environment) { + return true; + } + + @Override + public TypeResolver getTypeResolver(InterfaceWiringEnvironment environment) { + return new ReflectiveTypeResolver(); + } + + @Override + public boolean providesTypeResolver(UnionWiringEnvironment environment) { + return true; + } + + @Override + public TypeResolver getTypeResolver(UnionWiringEnvironment environment) { + return new ReflectiveTypeResolver(); + } +} \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/monitoring/MonitoringConfiguration.java b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/monitoring/MonitoringConfiguration.java new file mode 100644 index 0000000000..6f6284c6f1 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/monitoring/MonitoringConfiguration.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2024 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.infrastructure.monitoring; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +/** + * Configuration of the monitoring support for Sirius Web. + * + * @author hmarchadour + */ +@Configuration +public class MonitoringConfiguration { + @Bean + public MeterRegistry meterRegistry() { + return new SimpleMeterRegistry(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2024.01/01-initial-schema.xml b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2024.01/01-initial-schema.xml index 88cc947e43..3690a2bc2b 100644 --- a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2024.01/01-initial-schema.xml +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/resources/db/changelog/2024.01/01-initial-schema.xml @@ -28,6 +28,12 @@ + + + + + + ALTER TABLE project ADD CONSTRAINT project_name_length CHECK (char_length(name) > 0 AND char_length(name) <= 1024) @@ -47,5 +53,75 @@ ALTER TABLE nature ADD CONSTRAINT nature_name_length CHECK (char_length(name) > 0 AND char_length(name) <= 1024) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-starter/pom.xml b/packages/sirius-web/backend/sirius-web-starter/pom.xml index f924750b16..fc54a28554 100644 --- a/packages/sirius-web/backend/sirius-web-starter/pom.xml +++ b/packages/sirius-web/backend/sirius-web-starter/pom.xml @@ -49,6 +49,16 @@ sirius-web-infrastructure 2024.1.2 + + org.eclipse.sirius + sirius-components-graphql + 2024.1.2 + + + org.eclipse.sirius + sirius-components-web + 2024.1.2 + diff --git a/packages/sirius-web/backend/sirius-web-starter/src/main/java/org/eclipse/sirius/web/starter/SiriusWebStarterConfiguration.java b/packages/sirius-web/backend/sirius-web-starter/src/main/java/org/eclipse/sirius/web/starter/SiriusWebStarterConfiguration.java index 0ee2da9fdf..3980013010 100644 --- a/packages/sirius-web/backend/sirius-web-starter/src/main/java/org/eclipse/sirius/web/starter/SiriusWebStarterConfiguration.java +++ b/packages/sirius-web/backend/sirius-web-starter/src/main/java/org/eclipse/sirius/web/starter/SiriusWebStarterConfiguration.java @@ -12,7 +12,14 @@ *******************************************************************************/ package org.eclipse.sirius.web.starter; +import org.eclipse.sirius.components.graphql.ws.api.IGraphQLWebSocketHandlerListener; import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; /** * AutoConfiguration of the Sirius Web application. @@ -20,5 +27,33 @@ * @author sbegaudeau */ @AutoConfiguration +@ComponentScan(basePackages = { + "org.eclipse.sirius.components.core", + "org.eclipse.sirius.collaborative", + "org.eclipse.sirius.components.emf", + "org.eclipse.sirius.components.graphql", + "org.eclipse.sirius.components.web" +}) public class SiriusWebStarterConfiguration { + @Bean + @ConditionalOnMissingBean(IGraphQLWebSocketHandlerListener.class) + public IGraphQLWebSocketHandlerListener graphQLWebSocketHandlerListener() { + return new IGraphQLWebSocketHandlerListener() { + + @Override + public void handleTextMessage(WebSocketSession session, TextMessage message) { + // Do nothing + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) { + // Do nothing + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { + // Do nothing + } + }; + } } diff --git a/packages/sirius-web/frontend/sirius-web-application/src/router/RouterExtensionPoints.tsx b/packages/sirius-web/frontend/sirius-web-application/src/router/RouterExtensionPoints.tsx index a510cdf4f7..ae8a714b5f 100644 --- a/packages/sirius-web/frontend/sirius-web-application/src/router/RouterExtensionPoints.tsx +++ b/packages/sirius-web/frontend/sirius-web-application/src/router/RouterExtensionPoints.tsx @@ -12,9 +12,9 @@ *******************************************************************************/ import { DataExtensionPoint } from '@eclipse-sirius/sirius-components-core'; -import { RouterProps } from 'react-router-dom'; +import { RouteProps } from 'react-router-dom'; -export const routerExtensionPoint: DataExtensionPoint> = { +export const routerExtensionPoint: DataExtensionPoint> = { identifier: 'router#routes', fallback: [], }; diff --git a/packages/web/backend/sirius-components-web/pom.xml b/packages/web/backend/sirius-components-web/pom.xml index 2eb843a6e2..86519afb5b 100644 --- a/packages/web/backend/sirius-components-web/pom.xml +++ b/packages/web/backend/sirius-components-web/pom.xml @@ -1,6 +1,6 @@