Skip to content

Commit

Permalink
[1301] Adapt sirius-web code to support inter-model references
Browse files Browse the repository at this point in the history
* Use a correct URI to instantiate a JSONResource. The URI should have a
scheme "sirius"
* Only resources with "sirius" scheme are persisted and displayed in the
Explorer
* This commit also ensures that, if a specific resource factory has been
registered, it will be used to instantiate the XMI resource at download
* Forbid the upload of a single document that contains proxies. The
check is not done when uploading a project.

#1301
Signed-off-by: Laurent Fasani <laurent.fasani@obeo.fr>
  • Loading branch information
lfasani committed Oct 5, 2022
1 parent f3a08e0 commit bc4002c
Show file tree
Hide file tree
Showing 27 changed files with 437 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public CompletableFuture<IPayload> get(DataFetchingEnvironment environment) thro
.orElse(null);
// @formatter:on

UploadDocumentInput input = new UploadDocumentInput(id, editingContextId, file);
UploadDocumentInput input = new UploadDocumentInput(id, editingContextId, file, true);

// @formatter:off
return this.editingContextEventProcessorRegistry.dispatchEvent(input.getEditingContextId(), input)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import org.eclipse.emf.ecore.xmi.XMLParserPool;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
import org.eclipse.sirius.components.emf.services.SiriusWebJSONResourceFactoryImpl;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.components.emf.utils.EMFResourceUtils;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.slf4j.Logger;
Expand All @@ -53,7 +53,7 @@ public StereotypeBuilder(String timerName, MeterRegistry meterRegistry) {
}

public String getStereotypeBody(EObject rootEObject) {
JsonResource resource = new SiriusWebJSONResourceFactoryImpl().createResource(URI.createURI("inmemory")); //$NON-NLS-1$
JsonResource resource = new JSONResourceFactory().createResourceFromPath("inmemory"); //$NON-NLS-1$
if (rootEObject != null) {
resource.getContents().add(rootEObject);
}
Expand All @@ -78,7 +78,7 @@ public String getStereotypeBody(ClassPathResource classPathResource) {

String content = ""; //$NON-NLS-1$
try (var inputStream = classPathResource.getInputStream()) {
URI uri = URI.createURI(classPathResource.getFilename());
URI uri = new JSONResourceFactory().createResourceURI(classPathResource.getFilename());
Resource inputResource = this.loadFromXMI(uri, inputStream);
content = this.saveAsJSON(uri, inputResource);
} catch (IOException exception) {
Expand All @@ -100,7 +100,7 @@ private Resource loadFromXMI(URI uri, InputStream inputStream) throws IOExceptio

private String saveAsJSON(URI uri, Resource inputResource) throws IOException {
String content;
JsonResource ouputResource = new SiriusWebJSONResourceFactoryImpl().createResource(uri);
JsonResource ouputResource = new JSONResourceFactory().createResource(uri);
ouputResource.getContents().addAll(inputResource.getContents());
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
Map<String, Object> jsonSaveOptions = new EMFResourceUtils().getFastJSONSaveOptions();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2022 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.services.api.document;

import java.text.MessageFormat;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

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

/**
* The input object for the operation to rewrite broken proxy URIs in documents.
*
* @author pcdavid
*/
public class RewriteProxiesInput implements IInput {
private final UUID id;

private final String editingContextId;

private final Map<String, String> oldDocumentIdToNewDocumentId;

public RewriteProxiesInput(UUID id, String editingContextId, Map<String, String> oldDocumentIdToNewDocumentId) {
this.id = Objects.requireNonNull(id);
this.editingContextId = Objects.requireNonNull(editingContextId);
this.oldDocumentIdToNewDocumentId = Objects.requireNonNull(oldDocumentIdToNewDocumentId);
}

@Override
public UUID getId() {
return this.id;
}

public String getEditingContextId() {
return this.editingContextId;
}

public Map<String, String> getOldDocumentIdToNewDocumentId() {
return this.oldDocumentIdToNewDocumentId;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}, editingContextId: {2}, oldDocumentIdToNewDocumentId: {3}'}'"; //$NON-NLS-1$
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id, this.editingContextId, this.oldDocumentIdToNewDocumentId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************************
* Copyright (c) 2022 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.services.api.document;

import java.text.MessageFormat;
import java.util.Objects;
import java.util.UUID;

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

/**
* The payload of the rewrite proxies operation.
*
* @author pcdavid
*/
public final class RewriteProxiesSuccessPayload implements IPayload {

private final UUID id;

public RewriteProxiesSuccessPayload(UUID id) {
this.id = Objects.requireNonNull(id);
}

@Override
public UUID getId() {
return this.id;
}

@Override
public String toString() {
String pattern = "{0} '{'id: {1}'}'"; //$NON-NLS-1$
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,24 @@ public final class UploadDocumentInput implements IInput {

private final UploadFile file;

public UploadDocumentInput(UUID id, String editingContextId, UploadFile file) {
private final boolean checkProxies;

public UploadDocumentInput(UUID id, String editingContextId, UploadFile file, boolean checkProxies) {
this.id = Objects.requireNonNull(id);
this.editingContextId = Objects.requireNonNull(editingContextId);
this.file = Objects.requireNonNull(file);
this.checkProxies = checkProxies;
}

@Override
public UUID getId() {
return this.id;
}

public boolean isCheckProxies() {
return this.checkProxies;
}

public String getEditingContextId() {
return this.editingContextId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.util.Optional;
import java.util.UUID;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.sirius.components.collaborative.api.ChangeDescription;
Expand All @@ -33,7 +32,7 @@
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.core.configuration.StereotypeDescription;
import org.eclipse.sirius.components.emf.services.EditingContext;
import org.eclipse.sirius.components.emf.services.SiriusWebJSONResourceFactoryImpl;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.eclipse.sirius.web.services.api.document.Document;
import org.eclipse.sirius.web.services.api.document.IDocumentService;
Expand Down Expand Up @@ -136,9 +135,8 @@ private void createDocument(One<IPayload> payloadSink, Many<ChangeDescription> c
var optionalDocument = this.documentService.createDocument(editingContextId, name, stereotypeDescription.getContent());
if (optionalDocument.isPresent()) {
Document document = optionalDocument.get();
URI uri = URI.createURI(document.getId().toString());

JsonResource resource = new SiriusWebJSONResourceFactoryImpl().createResource(uri);
JsonResource resource = new JSONResourceFactory().createResourceFromPath(document.getId().toString());
try (var inputStream = new ByteArrayInputStream(document.getContent().getBytes())) {
resource.load(inputStream, null);
} catch (IOException exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.eclipse.sirius.components.core.api.IInput;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.emf.services.EditingContext;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.web.services.api.document.Document;
import org.eclipse.sirius.web.services.api.document.IDocumentService;
import org.eclipse.sirius.web.services.messages.IServicesMessageService;
Expand Down Expand Up @@ -96,7 +97,7 @@ public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDesc
Document document = optionalDocument.get();

ResourceSet resourceSet = editingDomain.getResourceSet();
URI uri = URI.createURI(document.getId().toString());
URI uri = new JSONResourceFactory().createResourceURI(document.getId().toString());

// @formatter:off
List<Resource> resourcesToDelete = resourceSet.getResources().stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.sirius.components.emf.services.IEditingContextEPackageService;
import org.eclipse.sirius.components.emf.services.SiriusWebJSONResourceFactoryImpl;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.eclipse.sirius.web.persistence.entities.DocumentEntity;
import org.eclipse.sirius.web.persistence.repositories.IDocumentRepository;
Expand Down Expand Up @@ -152,8 +152,7 @@ public Optional<byte[]> getBytes(Document document, String resourceKind) {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.setPackageRegistry(ePackageRegistryImpl);

URI uri = URI.createURI(document.getName());
JsonResource resource = new SiriusWebJSONResourceFactoryImpl().createResource(uri);
JsonResource resource = new JSONResourceFactory().createResourceFromPath(document.getName());
resourceSet.getResources().add(resource);
resourceSet.getResources().add(outputResource);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (c) 2022 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.services.documents;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.sirius.components.collaborative.api.ChangeDescription;
import org.eclipse.sirius.components.collaborative.api.ChangeKind;
import org.eclipse.sirius.components.collaborative.api.IEditingContextEventHandler;
import org.eclipse.sirius.components.core.api.ErrorPayload;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IInput;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.emf.services.EditingContext;
import org.eclipse.sirius.web.services.api.document.RewriteProxiesInput;
import org.eclipse.sirius.web.services.api.document.RewriteProxiesSuccessPayload;
import org.eclipse.sirius.web.services.messages.IServicesMessageService;
import org.springframework.stereotype.Service;

import reactor.core.publisher.Sinks.Many;
import reactor.core.publisher.Sinks.One;

/**
* The event handler to rewrite broken proxy URIs in documents (typically after an upload where the newly created
* documents have different ids).
*
* @author pcdavid
*/
@Service
public class RewriteProxiesEventHandler implements IEditingContextEventHandler {
private final IServicesMessageService messageService;

public RewriteProxiesEventHandler(IServicesMessageService messageService) {
this.messageService = Objects.requireNonNull(messageService);
}

@Override
public boolean canHandle(IEditingContext editingContext, IInput input) {
return input instanceof RewriteProxiesInput;
}

@Override
public void handle(One<IPayload> payloadSink, Many<ChangeDescription> changeDescriptionSink, IEditingContext editingContext, IInput input) {
IPayload payload = new ErrorPayload(input.getId(), this.messageService.unexpectedError());
ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, editingContext.getId(), input);

if (input instanceof RewriteProxiesInput && editingContext instanceof EditingContext) {
RewriteProxiesInput rewriteInput = (RewriteProxiesInput) input;
AdapterFactoryEditingDomain adapterFactoryEditingDomain = ((EditingContext) editingContext).getDomain();
int totalRewrittenCount = 0;
for (Resource resource : adapterFactoryEditingDomain.getResourceSet().getResources()) {
totalRewrittenCount += this.rewriteProxyURIs(resource, rewriteInput.getOldDocumentIdToNewDocumentId());
}
if (totalRewrittenCount > 0) {
changeDescription = new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input);
}
payload = new RewriteProxiesSuccessPayload(input.getId());
}

payloadSink.tryEmitValue(payload);
changeDescriptionSink.tryEmitNext(changeDescription);
}

private int rewriteProxyURIs(Resource resource, Map<String, String> oldDocumentIdToNewDocumentId) {
AtomicInteger rewrittenCount = new AtomicInteger();
resource.getAllContents().forEachRemaining(eObject -> {
eObject.eCrossReferences().forEach(target -> {
InternalEObject internalEObject = (InternalEObject) target;
if (internalEObject.eIsProxy()) {
URI proxyURI = internalEObject.eProxyURI();
String oldDocumentId = proxyURI.path().substring(1);
String newDocumentId = oldDocumentIdToNewDocumentId.get(oldDocumentId);
if (newDocumentId != null) {
String prefix = EditingContext.RESOURCE_SCHEME + ":///"; //$NON-NLS-1$
URI newProxyURI = URI.createURI(proxyURI.toString().replace(prefix + oldDocumentId, prefix + newDocumentId));
internalEObject.eSetProxyURI(newProxyURI);
rewrittenCount.incrementAndGet();
}
}
});
});
return rewrittenCount.get();
}

}
Loading

0 comments on commit bc4002c

Please sign in to comment.