Skip to content

Commit

Permalink
[3777] Support any object as semantic element in the tree representation
Browse files Browse the repository at this point in the history
+ Add a virtual node for grouping super types of Entity nodes as an example

Bug: #3777
Signed-off-by: Jerome Gout <jerome.gout@obeosoft.com>
Signed-off-by: Stéphane Bégaudeau <stephane.begaudeau@obeo.fr>
  • Loading branch information
jerome-obeo authored and sbegaudeau committed Aug 14, 2024
1 parent 53d5013 commit 8aa985d
Show file tree
Hide file tree
Showing 20 changed files with 495 additions and 122 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ A migration participant has been added to automatically keep compatible all diag
- https://github.com/eclipse-sirius/sirius-web/issues/3801[#3801] Add an equivalent of IViewDiagramDescriptionSearchService for Form descriptions
- https://github.com/eclipse-sirius/sirius-web/issues/3557[#3550] [sirius-web] Add an extension point to contribute setting pages
- https://github.com/eclipse-sirius/sirius-web/issues/3776[#3776] [trees] Remove unwanted dependency from the reference widget in the explorer
- https://github.com/eclipse-sirius/sirius-web/issues/3777[#3777] [sirius-web] Add support for any kind of object as semantic element in the tree representation


== v2024.7.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ private TreeDescription getModelBrowserDescription(String descriptionId, Predica
.canCreatePredicate(canCreatePredicate)
.deleteHandler(this::getDeleteHandler)
.renameHandler(this::getRenameHandler)
.treeItemObjectProvider(this::getTreeItemObject)
.build();
}

Expand Down Expand Up @@ -397,4 +398,13 @@ private IStatus getDeleteHandler(VariableManager variableManager) {
private IStatus getRenameHandler(VariableManager variableManager, String newLabel) {
return new Failure("");
}

private Object getTreeItemObject(VariableManager variableManager) {
var optionalEditingContext = variableManager.get(IEditingContext.EDITING_CONTEXT, IEditingContext.class);
var optionalId = variableManager.get(TreeDescription.ID, String.class);
if (optionalId.isPresent() && optionalEditingContext.isPresent()) {
return this.objectService.getObject(optionalEditingContext.get(), optionalId.get());
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@
*******************************************************************************/
package org.eclipse.sirius.web.application.views.explorer.services;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.sirius.components.collaborative.api.ChangeKind;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext;
import org.eclipse.sirius.components.representations.Failure;
import org.eclipse.sirius.components.representations.IStatus;
import org.eclipse.sirius.components.representations.Success;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.components.trees.description.TreeDescription;
import org.eclipse.sirius.web.application.views.explorer.services.api.IDeleteTreeItemHandler;
import org.springframework.stereotype.Service;

Expand All @@ -38,29 +40,39 @@
@Service
public class DeleteDocumentTreeItemEventHandler implements IDeleteTreeItemHandler {

private final IRepresentationDescriptionSearchService representationDescriptionSearchService;

public DeleteDocumentTreeItemEventHandler(IRepresentationDescriptionSearchService representationDescriptionSearchService) {
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
}

@Override
public boolean canHandle(IEditingContext editingContext, TreeItem treeItem) {
return treeItem.getKind().equals(ExplorerDescriptionProvider.DOCUMENT_KIND);
}

@Override
public IStatus handle(IEditingContext editingContext, TreeItem treeItem) {
public IStatus handle(IEditingContext editingContext, TreeItem treeItem, Tree tree) {
var optionalTreeDescription = this.representationDescriptionSearchService.findById(editingContext, tree.getDescriptionId())
.filter(TreeDescription.class::isInstance)
.map(TreeDescription.class::cast);

var optionalEditingDomain = Optional.of(editingContext)
.filter(IEMFEditingContext.class::isInstance)
.map(IEMFEditingContext.class::cast)
.map(IEMFEditingContext::getDomain);

if (optionalEditingDomain.isPresent()) {
var editingDomain = optionalEditingDomain.get();
ResourceSet resourceSet = editingDomain.getResourceSet();
URI uri = new JSONResourceFactory().createResourceURI(treeItem.getId());

List<Resource> resourcesToDelete = resourceSet.getResources().stream()
.filter(resource -> resource.getURI().equals(uri))
.toList();
resourcesToDelete.forEach(resourceSet.getResources()::remove);
if (optionalEditingDomain.isPresent() && optionalTreeDescription.isPresent()) {
var variableManager = new VariableManager();
variableManager.put(IEditingContext.EDITING_CONTEXT, editingContext);
variableManager.put(TreeDescription.ID, treeItem.getId());

return new Success(ChangeKind.SEMANTIC_CHANGE, Map.of());
var object = optionalTreeDescription.get().getTreeItemObjectProvider().apply(variableManager);
if (object instanceof Resource resource) {
ResourceSet resourceSet = optionalEditingDomain.get().getResourceSet();
resourceSet.getResources().remove(resource);
return new Success(ChangeKind.SEMANTIC_CHANGE, Map.of());
}
}
return new Failure("");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@

import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.eclipse.sirius.components.collaborative.api.ChangeKind;
import org.eclipse.sirius.components.core.api.IEditService;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.core.api.SemanticKindConstants;
import org.eclipse.sirius.components.representations.Failure;
import org.eclipse.sirius.components.representations.IStatus;
import org.eclipse.sirius.components.representations.Success;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.components.trees.description.TreeDescription;
import org.eclipse.sirius.web.application.views.explorer.services.api.IDeleteTreeItemHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -40,13 +42,13 @@ public class DeleteObjectTreeItemEventHandler implements IDeleteTreeItemHandler

private final Logger logger = LoggerFactory.getLogger(DeleteObjectTreeItemEventHandler.class);

private final IObjectSearchService objectSearchService;

private final IEditService editService;

public DeleteObjectTreeItemEventHandler(IObjectSearchService objectSearchService, IEditService editService) {
this.objectSearchService = Objects.requireNonNull(objectSearchService);
private final IRepresentationDescriptionSearchService representationDescriptionSearchService;

public DeleteObjectTreeItemEventHandler(IEditService editService, IRepresentationDescriptionSearchService representationDescriptionSearchService) {
this.editService = Objects.requireNonNull(editService);
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
}

@Override
Expand All @@ -55,16 +57,27 @@ public boolean canHandle(IEditingContext editingContext, TreeItem treeItem) {
}

@Override
public IStatus handle(IEditingContext editingContext, TreeItem treeItem) {
Optional<Object> optionalObject = this.objectSearchService.getObject(editingContext, treeItem.getId());
if (optionalObject.isPresent()) {
Object object = optionalObject.get();
this.editService.delete(object);
public IStatus handle(IEditingContext editingContext, TreeItem treeItem, Tree tree) {
IStatus result = new Failure("");
var optionalTreeDescription = this.representationDescriptionSearchService.findById(editingContext, tree.getDescriptionId())
.filter(TreeDescription.class::isInstance)
.map(TreeDescription.class::cast);

if (optionalTreeDescription.isPresent()) {
var variableManager = new VariableManager();
variableManager.put(IEditingContext.EDITING_CONTEXT, editingContext);
variableManager.put(TreeDescription.ID, treeItem.getId());

return new Success(ChangeKind.SEMANTIC_CHANGE, Map.of());
var object = optionalTreeDescription.get().getTreeItemObjectProvider().apply(variableManager);
if (object != null) {
this.editService.delete(object);
result = new Success(ChangeKind.SEMANTIC_CHANGE, Map.of());
} else {
this.logger.warn("The object with the id {} does not exist", treeItem.getId());
}
} else {
this.logger.warn("The object with the id {} does not exist", treeItem.getId());
this.logger.warn("Unable to retrieve the tree description with the id {}", tree.getDescriptionId());
}
return new Failure("");
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.eclipse.sirius.components.representations.IRepresentation;
import org.eclipse.sirius.components.representations.IStatus;
import org.eclipse.sirius.components.representations.Success;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.web.application.views.explorer.services.api.IDeleteTreeItemHandler;
import org.springframework.stereotype.Service;
Expand All @@ -39,7 +40,7 @@ public boolean canHandle(IEditingContext editingContext, TreeItem treeItem) {
}

@Override
public IStatus handle(IEditingContext editingContext, TreeItem treeItem) {
public IStatus handle(IEditingContext editingContext, TreeItem treeItem, Tree tree) {
Map<String, Object> parameters = new HashMap<>();
parameters.put(EditingContextEventProcessor.REPRESENTATION_ID, treeItem.getId());
return new Success(ChangeKind.REPRESENTATION_TO_DELETE, parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,23 @@

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.sirius.components.collaborative.trees.api.IExpandAllTreePathProvider;
import org.eclipse.sirius.components.collaborative.trees.dto.ExpandAllTreePathInput;
import org.eclipse.sirius.components.collaborative.trees.dto.ExpandAllTreePathSuccessPayload;
import org.eclipse.sirius.components.collaborative.trees.dto.TreePath;
import org.eclipse.sirius.components.core.api.IContentService;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.core.api.IPayload;
import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.domain.Entity;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.description.TreeDescription;
import org.eclipse.sirius.web.application.views.explorer.services.api.IExplorerNavigationService;
import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.services.api.IRepresentationDataSearchService;
import org.springframework.stereotype.Service;
Expand All @@ -40,8 +43,6 @@
@Service
public class ExpandAllTreePathProvider implements IExpandAllTreePathProvider {

private final IObjectSearchService objectSearchService;

private final IIdentityService identityService;

private final IContentService contentService;
Expand All @@ -50,11 +51,13 @@ public class ExpandAllTreePathProvider implements IExpandAllTreePathProvider {

private final IRepresentationDataSearchService representationDataSearchService;

public ExpandAllTreePathProvider(IObjectSearchService objectSearchService, IIdentityService identityService, IContentService contentService, IExplorerNavigationService explorerNavigationService, IRepresentationDataSearchService representationDataSearchService) {
this.objectSearchService = Objects.requireNonNull(objectSearchService);
private final IRepresentationDescriptionSearchService representationDescriptionSearchService;

public ExpandAllTreePathProvider(IIdentityService identityService, IContentService contentService, IExplorerNavigationService explorerNavigationService, IRepresentationDescriptionSearchService representationDescriptionSearchService, IRepresentationDataSearchService representationDataSearchService) {
this.identityService = Objects.requireNonNull(identityService);
this.contentService = Objects.requireNonNull(contentService);
this.explorerNavigationService = Objects.requireNonNull(explorerNavigationService);
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
this.representationDataSearchService = Objects.requireNonNull(representationDataSearchService);
}

Expand All @@ -67,53 +70,55 @@ public boolean canHandle(Tree tree) {
public IPayload handle(IEditingContext editingContext, Tree tree, ExpandAllTreePathInput input) {
int maxDepth = 0;
String treeItemId = input.treeItemId();

Set<String> treeItemIdsToExpand = new LinkedHashSet<>();
var object = this.objectSearchService.getObject(editingContext, treeItemId);
if (object.isPresent()) {
var object = this.getTreeItemObject(editingContext, treeItemId, tree);
if (object instanceof EObject) {
// We need to get the current depth of the tree item
var itemAncestors = this.explorerNavigationService.getAncestors(editingContext, treeItemId);
var itemAncestors = this.explorerNavigationService.getAncestors(editingContext, treeItemId, tree);
maxDepth = itemAncestors.size();
maxDepth = this.addAllContents(editingContext, treeItemId, maxDepth, treeItemIdsToExpand);
} else {
maxDepth = this.addAllContents(editingContext, treeItemId, maxDepth, treeItemIdsToExpand, tree);
} else if (object instanceof Resource resource) {
// The object may be a document
var optionalEditingDomain = Optional.of(editingContext).filter(IEMFEditingContext.class::isInstance)
.map(IEMFEditingContext.class::cast)
.map(IEMFEditingContext::getDomain);

if (optionalEditingDomain.isPresent()) {
var optionalResource = optionalEditingDomain.get().getResourceSet().getResources().stream()
.filter(resource -> treeItemId.equals(resource.getURI().path().substring(1)))
.findFirst();
if (optionalResource.isPresent()) {
var contents = optionalResource.get().getContents();
if (!contents.isEmpty()) {
treeItemIdsToExpand.add(treeItemId);
for (var rootObject : contents) {
var rootObjectId = this.identityService.getId(rootObject);
var rootObjectTreePathMaxDepth = 1;
rootObjectTreePathMaxDepth = this.addAllContents(editingContext, rootObjectId, rootObjectTreePathMaxDepth, treeItemIdsToExpand);
maxDepth = Math.max(maxDepth, rootObjectTreePathMaxDepth);
}
}
var contents = resource.getContents();
if (!contents.isEmpty()) {
treeItemIdsToExpand.add(treeItemId);
for (var rootObject : contents) {
var rootObjectId = this.identityService.getId(rootObject);
var rootObjectTreePathMaxDepth = 1;
rootObjectTreePathMaxDepth = this.addAllContents(editingContext, rootObjectId, rootObjectTreePathMaxDepth, treeItemIdsToExpand, tree);
maxDepth = Math.max(maxDepth, rootObjectTreePathMaxDepth);
}
}
}
return new ExpandAllTreePathSuccessPayload(input.id(), new TreePath(treeItemIdsToExpand.stream().toList(), maxDepth));
}

private int addAllContents(IEditingContext editingContext, String treeItemId, int depth, Set<String> treeItemIdsToExpand) {
private int addAllContents(IEditingContext editingContext, String treeItemId, int depth, Set<String> treeItemIdsToExpand, Tree tree) {
var depthConsidered = depth;
Optional<Object> optionalObject = this.objectSearchService.getObject(editingContext, treeItemId);
if (optionalObject.isPresent()) {
var contents = this.contentService.getContents(optionalObject.get());
var object = this.getTreeItemObject(editingContext, treeItemId, tree);

if (object instanceof EObject eObject) {
if (object instanceof Entity entity) {
// an Entity has a virtual node for its super types, this node should be a child of the Entity
var id = ExplorerDescriptionProvider.SETTING + this.identityService.getId(entity) + ExplorerDescriptionProvider.SETTING_ID_SEPARATOR + "superTypes";
treeItemIdsToExpand.add(id);
var superTypes = entity.getSuperTypes();
if (superTypes.size() > 0) {
depthConsidered = Math.max(depthConsidered, depth + 2);
} else {
depthConsidered = Math.max(depthConsidered, depth + 1);
}
}
var contents = this.contentService.getContents(eObject);
if (!contents.isEmpty()) {
treeItemIdsToExpand.add(treeItemId);

for (var child : contents) {
String childId = this.identityService.getId(child);
treeItemIdsToExpand.add(childId);
var childTreePathMaxDepth = depth + 1;
childTreePathMaxDepth = this.addAllContents(editingContext, childId, childTreePathMaxDepth, treeItemIdsToExpand);
childTreePathMaxDepth = this.addAllContents(editingContext, childId, childTreePathMaxDepth, treeItemIdsToExpand, tree);
depthConsidered = Math.max(depthConsidered, childTreePathMaxDepth);
}
} else if (this.representationDataSearchService.existAnyRepresentationForTargetObjectId(treeItemId)) {
Expand All @@ -124,4 +129,18 @@ private int addAllContents(IEditingContext editingContext, String treeItemId, in

return depthConsidered;
}

private Object getTreeItemObject(IEditingContext editingContext, String treeItemId, Tree tree) {
var optionalTreeDescription = this.representationDescriptionSearchService.findById(editingContext, tree.getDescriptionId())
.filter(TreeDescription.class::isInstance)
.map(TreeDescription.class::cast);

if (optionalTreeDescription.isPresent()) {
var variableManager = new VariableManager();
variableManager.put(IEditingContext.EDITING_CONTEXT, editingContext);
variableManager.put(TreeDescription.ID, treeItemId);
return optionalTreeDescription.get().getTreeItemObjectProvider().apply(variableManager);
}
return null;
}
}
Loading

0 comments on commit 8aa985d

Please sign in to comment.