Skip to content

Commit

Permalink
[3740] Add support for object duplication from Explorer
Browse files Browse the repository at this point in the history
Bug: #3740
Signed-off-by: Laurent Fasani <[email protected]>
Signed-off-by: Florian ROUËNÉ <[email protected]>
  • Loading branch information
lfasani authored and frouene committed Dec 31, 2024
1 parent 4b778e9 commit 005092d
Show file tree
Hide file tree
Showing 25 changed files with 1,596 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

=== New Features

- https://github.com/eclipse-sirius/sirius-web/issues/3740[#3740] [sirius-web] Add support for object duplication from explorer

=== Improvements

Expand Down
5 changes: 3 additions & 2 deletions doc/iterations/2024.9/add_support_for_object_duplication.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ Currently, it is not possible to duplicate an object from the Explorer.
== Key Result

The user can duplicate a semantic object with contextual menu on tree items in the explorer.
The user can choose
The user can choose

* the target container where the duplicated object will be added
* the target containment feature
* options to define how is duplicated the content of the duplicated object
Expand Down Expand Up @@ -72,4 +73,4 @@ Nothing identified

== No-gos

Nothing identified
Nothing identified
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* 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.components.emf.utils;

import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;

/**
* This class inherits from org.eclipse.emf.ecore.util.EcoreUtil.Copier to leverage protected methods.
*
* @author lfasani
*/
public class SiriusEMFCopier extends EcoreUtil.Copier {

/*
* This method copies the EObject with all its attributes but not its cross references nor its content.
* This code is partially copied from org.eclipse.emf.ecore.util.EcoreUtil.Copier.copy
* */
public EObject copyWithoutContent(EObject eObject) {
if (eObject == null) {
return null;
} else {
EObject copyEObject = this.createCopy(eObject);
if (copyEObject != null) {
this.put(eObject, copyEObject);
EClass eClass = eObject.eClass();
for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i) {
EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i);
if (eStructuralFeature.isChangeable() && !eStructuralFeature.isDerived()) {
if (eStructuralFeature instanceof EAttribute) {
this.copyAttribute((EAttribute) eStructuralFeature, eObject, copyEObject);
}
}
}

this.copyProxyURI(eObject, copyEObject);
}

return copyEObject;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*******************************************************************************
* 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.object;

import java.util.UUID;

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

/**
* The input of the duplicate dialog tree event subscription.
*
* @author frouene
*/
public record DuplicateDialogTreeEventInput(UUID id, String editingContextId, String representationId) implements IInput {

}
Original file line number Diff line number Diff line change
@@ -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.object;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.eclipse.sirius.components.annotations.spring.graphql.SubscriptionDataFetcher;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.IEventProcessorSubscriptionProvider;
import org.eclipse.sirius.components.graphql.api.IExceptionWrapper;
import org.eclipse.sirius.components.graphql.api.LocalContextConstants;
import org.reactivestreams.Publisher;

import graphql.execution.DataFetcherResult;
import graphql.schema.DataFetchingEnvironment;

/**
* The data fetcher used to send the refreshed tree to a duplicate dialog subscription .
*
* @author frouene
*/
@SubscriptionDataFetcher(type = "Subscription", field = "duplicateDialogTreeEvent")
public class SubscriptionDuplicateDialogTreeEventDataFetcher implements IDataFetcherWithFieldCoordinates<Publisher<DataFetcherResult<IPayload>>> {

private static final String INPUT_ARGUMENT = "input";

private final ObjectMapper objectMapper;

private final IExceptionWrapper exceptionWrapper;

private final IEventProcessorSubscriptionProvider eventProcessorSubscriptionProvider;

public SubscriptionDuplicateDialogTreeEventDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEventProcessorSubscriptionProvider eventProcessorSubscriptionProvider) {
this.objectMapper = Objects.requireNonNull(objectMapper);
this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper);
this.eventProcessorSubscriptionProvider = Objects.requireNonNull(eventProcessorSubscriptionProvider);
}

@Override
public Publisher<DataFetcherResult<IPayload>> get(DataFetchingEnvironment environment) throws Exception {
Object argument = environment.getArgument(INPUT_ARGUMENT);
var input = this.objectMapper.convertValue(argument, DuplicateDialogTreeEventInput.class);

Map<String, Object> localContext = new HashMap<>();
localContext.put(LocalContextConstants.EDITING_CONTEXT_ID, input.editingContextId());
localContext.put(LocalContextConstants.REPRESENTATION_ID, input.representationId());

return this.exceptionWrapper.wrapFlux(() -> this.eventProcessorSubscriptionProvider.getSubscription(input.editingContextId(), input.representationId(), input), input)
.map(payload -> DataFetcherResult.<IPayload>newResult()
.data(payload)
.localContext(localContext)
.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*******************************************************************************
* 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.views.explorer.controllers;

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

import org.eclipse.sirius.components.annotations.spring.graphql.QueryDataFetcher;
import org.eclipse.sirius.components.collaborative.api.IEditingContextEventProcessorRegistry;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.web.application.views.explorer.dto.EditingContextContainmentFeatureNamesInput;

import graphql.schema.DataFetchingEnvironment;

/**
* Data fetcher for the field EditingContext#containmentFeatureNames.
* It is used to find the containment feature names of a container object given the candidate contained object.
*
* @author lfasani
*/
@QueryDataFetcher(type = "EditingContext", field = "containmentFeatureNames")
public class EditingContextContainmentFeatureNamesDataFetcher implements IDataFetcherWithFieldCoordinates<CompletableFuture<IPayload>> {
private static final String CONTAINER_ID = "containerId";

private static final String CONTAINED_OBJECT_ID = "containedObjectId";

private final IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry;

public EditingContextContainmentFeatureNamesDataFetcher(IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry) {
this.editingContextEventProcessorRegistry = Objects.requireNonNull(editingContextEventProcessorRegistry);
}

@Override
public CompletableFuture<IPayload> get(DataFetchingEnvironment environment) throws Exception {
String editingContextId = environment.getSource();
String containerId = environment.getArgument(CONTAINER_ID);
String containedObjectId = environment.getArgument(CONTAINED_OBJECT_ID);

EditingContextContainmentFeatureNamesInput input = new EditingContextContainmentFeatureNamesInput(UUID.randomUUID(), editingContextId, containerId, containedObjectId);
return this.editingContextEventProcessorRegistry.dispatchEvent(editingContextId, input)
.toFuture();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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.views.explorer.controllers;

import com.fasterxml.jackson.databind.ObjectMapper;

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

import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates;
import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher;
import org.eclipse.sirius.web.application.views.explorer.dto.DuplicateObjectInput;

import graphql.schema.DataFetchingEnvironment;

/**
* Data fetcher for the field Mutation#duplicateObject.
*
* @author lfasani
*/
@MutationDataFetcher(type = "Mutation", field = "duplicateObject")
public class MutationDuplicateObjectDataFetcher implements IDataFetcherWithFieldCoordinates<CompletableFuture<IPayload>> {

private static final String INPUT_ARGUMENT = "input";

private final ObjectMapper objectMapper;

private final IEditingContextDispatcher editingContextDispatcher;

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

@Override
public CompletableFuture<IPayload> get(DataFetchingEnvironment environment) throws Exception {
Object argument = environment.getArgument(INPUT_ARGUMENT);
var input = this.objectMapper.convertValue(argument, DuplicateObjectInput.class);

return this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input).toFuture();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*******************************************************************************
* 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.views.explorer.dto;

import java.util.UUID;

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

import jakarta.validation.constraints.NotNull;

/**
* The input object of the duplicate object mutation.
*
* @author lfasani
*/
public record DuplicateObjectInput(@NotNull UUID id, @NotNull String editingContextId, @NotNull String objectId, @NotNull String containerId, @NotNull String containmentFeatureName,
@NotNull Boolean duplicateContent, @NotNull Boolean copyOutgoingReferences, Boolean updateIncomingReferences) implements IInput {
}
Original file line number Diff line number Diff line change
@@ -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.application.views.explorer.dto;

import java.util.List;
import java.util.UUID;

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

import jakarta.validation.constraints.NotNull;

/**
* The payload of the duplicate object mutation.
*
* @author lfasani
*/
public record DuplicateObjectSuccessPayload(@NotNull UUID id, @NotNull Object object, @NotNull List<Message> messages) implements IPayload {
}
Original file line number Diff line number Diff line change
@@ -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.application.views.explorer.dto;

import java.util.UUID;

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

import jakarta.validation.constraints.NotNull;

/**
* The input object for this query.
*
* @author lfasani
*/
public record EditingContextContainmentFeatureNamesInput(@NotNull UUID id, @NotNull String editingContextId, @NotNull String containerId, @NotNull String containedObjectId) implements IInput {
}
Loading

0 comments on commit 005092d

Please sign in to comment.