Skip to content

Commit

Permalink
[3882] Add a new tree event to support non explorer tree descriptions
Browse files Browse the repository at this point in the history
+ an example of tree representation for Domain elements

Bug: #3882
Signed-off-by: Jerome Gout <[email protected]>
  • Loading branch information
jerome-obeo committed Aug 30, 2024
1 parent 71bf311 commit 5a2801d
Show file tree
Hide file tree
Showing 28 changed files with 1,465 additions and 151 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ A migration participant has been added to automatically keep compatible all diag
- https://github.com/eclipse-sirius/sirius-web/issues/3897[#3897] [sirius-web] Improve the search for projects
- https://github.com/eclipse-sirius/sirius-web/issues/3902[#3902] [core] Move the Help menu entry at the last position (after any contributed entries)
- https://github.com/eclipse-sirius/sirius-web/issues/3875[#3875] [sirius-web] Move explorer related code from sirius-components-trees to sirius-web-application
- https://github.com/eclipse-sirius/sirius-web/issues/3882[#3882] [sirius-web] Add a new tree event to handle tree description which are not explorer-related

== v2024.7.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
package org.eclipse.sirius.web.application.views.explorer.services;

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

Expand All @@ -28,7 +27,6 @@
import org.eclipse.sirius.components.core.api.IIdentityService;
import org.eclipse.sirius.components.core.api.IPayload;
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;
Expand Down Expand Up @@ -74,7 +72,7 @@ public IPayload handle(IEditingContext editingContext, Tree tree, ExpandAllTreeP

Set<String> treeItemIdsToExpand = new LinkedHashSet<>();
var object = this.getTreeItemObject(editingContext, tree, treeItemId);
if (object instanceof EObject || treeItemId.startsWith(ExplorerDescriptionProvider.SETTING)) {
if (object instanceof EObject) {
// We need to get the current depth of the tree item
var itemAncestors = this.explorerNavigationService.getAncestors(editingContext, tree, treeItemId);
maxDepth = itemAncestors.size();
Expand All @@ -99,27 +97,7 @@ private int addAllContents(IEditingContext editingContext, String treeItemId, in
var depthConsidered = depth;
var object = this.getTreeItemObject(editingContext, tree, treeItemId);

if (treeItemId.startsWith(ExplorerDescriptionProvider.SETTING) && object instanceof List<?> list) {
treeItemIdsToExpand.add(treeItemId);
for (var child : list) {
String childId = this.identityService.getId(child);
treeItemIdsToExpand.add(childId);
var childTreePathMaxDepth = depth + 1;
childTreePathMaxDepth = this.addAllContents(editingContext, childId, childTreePathMaxDepth, treeItemIdsToExpand, tree);
depthConsidered = Math.max(depthConsidered, childTreePathMaxDepth);
}
} else 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);
}
}
if (object instanceof EObject eObject) {
var contents = this.contentService.getContents(eObject);
if (!contents.isEmpty()) {
treeItemIdsToExpand.add(treeItemId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,16 @@
package org.eclipse.sirius.web.application.views.explorer.services;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.sirius.components.core.RepresentationMetadata;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.core.api.IRepresentationMetadataSearchService;
import org.eclipse.sirius.components.domain.Entity;
import org.eclipse.sirius.components.representations.VariableManager;
import org.eclipse.sirius.components.trees.renderer.TreeRenderer;
import org.eclipse.sirius.web.application.views.explorer.services.api.IExplorerChildrenProvider;
Expand Down Expand Up @@ -71,15 +67,6 @@ public boolean hasChildren(VariableManager variableManager) {
String id = this.objectService.getId(eObject);
hasChildren = this.representationDataSearchService.existAnyRepresentationForTargetObjectId(id);
}

if (!hasChildren && self instanceof Entity) {
hasChildren = true;
}
} else if (self instanceof Setting setting) {
var value = setting.get(true);
if (value instanceof Collection<?> collection) {
hasChildren = !collection.isEmpty();
}
}
return hasChildren;
}
Expand Down Expand Up @@ -130,17 +117,8 @@ private List<Object> getDefaultChildren(VariableManager variableManager) {
representationMetadata.sort(Comparator.comparing(RepresentationMetadata::getLabel));
result.addAll(representationMetadata);
List<Object> contents = this.objectService.getContents(self);
if (self instanceof Entity entity) {
result.add(((InternalEObject) entity).eSetting(entity.eClass().getEStructuralFeature("superTypes")));
}
result.addAll(contents);
} else if (self instanceof Setting setting) {
var value = setting.get(true);
if (value instanceof Collection<?> collection) {
result.addAll(collection);
}
}

}
}
return result;
Expand All @@ -167,8 +145,6 @@ private String getTreeItemId(VariableManager variableManager) {
id = resource.getURI().path().substring(1);
} else if (self instanceof EObject) {
id = this.objectService.getId(self);
} else if (self instanceof Setting setting) {
id = ExplorerDescriptionProvider.SETTING + this.objectService.getId(setting.getEObject()) + ExplorerDescriptionProvider.SETTING_ID_SEPARATOR + setting.getEStructuralFeature().getName();
}
return id;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.sirius.components.collaborative.api.IRepresentationImageProvider;
Expand Down Expand Up @@ -70,10 +68,6 @@ public class ExplorerDescriptionProvider implements IEditingContextRepresentatio

public static final String REPRESENTATION_NAME = "Explorer";

public static final String SETTING = "setting:";

public static final String SETTING_ID_SEPARATOR = "::";

private final IObjectService objectService;

private final IURLParser urlParser;
Expand Down Expand Up @@ -160,8 +154,6 @@ private String getTreeItemId(VariableManager variableManager) {
id = resource.getURI().path().substring(1);
} else if (self instanceof EObject) {
id = this.objectService.getId(self);
} else if (self instanceof Setting setting) {
id = SETTING + this.objectService.getId(setting.getEObject()) + SETTING_ID_SEPARATOR + setting.getEStructuralFeature().getName();
}
return id;
}
Expand All @@ -173,8 +165,6 @@ private String getKind(VariableManager variableManager) {
kind = representationMetadata.getKind();
} else if (self instanceof Resource) {
kind = DOCUMENT_KIND;
} else if (self instanceof Setting) {
kind = "setting";
} else {
kind = this.objectService.getKind(self);
}
Expand All @@ -197,8 +187,6 @@ private StyledString getLabel(VariableManager variableManager) {
var kind = this.objectService.getKind(self);
label = this.urlParser.getParameterValues(kind).get(SemanticKindConstants.ENTITY_ARGUMENT).get(0);
}
} else if (self instanceof Setting setting) {
label = setting.getEStructuralFeature().getName();
}
return StyledString.of(label);
}
Expand Down Expand Up @@ -302,36 +290,24 @@ private Object getTreeItemObject(VariableManager variableManager) {
if (optionalEditingContext.isPresent() && optionalTreeItemId.isPresent()) {
var treeItemId = optionalTreeItemId.get();
var editingContext = optionalEditingContext.get();

if (treeItemId.startsWith(SETTING)) {
// the tree item is a setting, get the object and then the structural feature associated
var objectId = treeItemId.substring(SETTING.length(), treeItemId.indexOf(SETTING_ID_SEPARATOR));
var featureName = treeItemId.substring(treeItemId.indexOf(SETTING_ID_SEPARATOR) + SETTING_ID_SEPARATOR.length());
var optObject = this.objectService.getObject(editingContext, objectId);
if (optObject.isPresent()) {
InternalEObject internalObject = (InternalEObject) optObject.get();
result = internalObject.eSetting(internalObject.eClass().getEStructuralFeature(featureName));
}
var optionalObject = this.objectService.getObject(editingContext, treeItemId);
if (optionalObject.isPresent()) {
result = optionalObject.get();
} else {
var optionalObject = this.objectService.getObject(editingContext, treeItemId);
if (optionalObject.isPresent()) {
result = optionalObject.get();
} else {
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(treeItemId);

result = resourceSet.getResources().stream()
.filter(resource -> resource.getURI().equals(uri))
.findFirst()
.orElse(null);
}
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(treeItemId);

result = resourceSet.getResources().stream()
.filter(resource -> resource.getURI().equals(uri))
.findFirst()
.orElse(null);
}
}
}
Expand All @@ -354,9 +330,6 @@ private Object getParentObject(VariableManager variableManager) {
semanticContainer = eObject.eResource();
}
result = semanticContainer;
} else if (self instanceof Setting setting) {
// the parent of the superTypes node is the object associated to this Setting
result = setting.getEObject();
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*******************************************************************************
* 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.tree;

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

import org.eclipse.emf.ecore.EObject;
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.IPayload;
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;

/**
* ExpandAll tree path provider for Domain tree representation example.
*
* @author Jerome Gout
*/
@Service
public class DomainExpandAllTreePathProvider implements IExpandAllTreePathProvider {

private final IIdentityService identityService;

private final IContentService contentService;

private final IExplorerNavigationService explorerNavigationService;

private final IRepresentationDataSearchService representationDataSearchService;

private final IRepresentationDescriptionSearchService representationDescriptionSearchService;
public DomainExpandAllTreePathProvider(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);
}

@Override
public boolean canHandle(Tree tree) {
return tree.getDescriptionId().equals(DomainTreeDescriptionProvider.DESCRIPTION_ID);
}

@Override
public IPayload handle(IEditingContext editingContext, Tree tree, ExpandAllTreePathInput input) {
int maxDepth = 0;
String treeItemId = input.treeItemId();

Set<String> treeItemIdsToExpand = new LinkedHashSet<>();
var object = this.getTreeItemObject(editingContext, tree, treeItemId);
if (object instanceof EObject || treeItemId.startsWith(DomainTreeDescriptionProvider.SETTING)) {
// We need to get the current depth of the tree item
var itemAncestors = this.explorerNavigationService.getAncestors(editingContext, tree, treeItemId);
maxDepth = itemAncestors.size();
maxDepth = this.addAllContents(editingContext, treeItemId, maxDepth, treeItemIdsToExpand, tree);
}
return new ExpandAllTreePathSuccessPayload(input.id(), new TreePath(treeItemIdsToExpand.stream().toList(), maxDepth));
}

private int addAllContents(IEditingContext editingContext, String treeItemId, int depth, Set<String> treeItemIdsToExpand, Tree tree) {
var depthConsidered = depth;
var object = this.getTreeItemObject(editingContext, tree, treeItemId);
if (treeItemId.startsWith(DomainTreeDescriptionProvider.SETTING) && object instanceof List<?> list) {
treeItemIdsToExpand.add(treeItemId);
for (var child : list) {
String childId = this.identityService.getId(child);
treeItemIdsToExpand.add(childId);
var childTreePathMaxDepth = depth + 1;
childTreePathMaxDepth = this.addAllContents(editingContext, childId, childTreePathMaxDepth, treeItemIdsToExpand, tree);
depthConsidered = Math.max(depthConsidered, childTreePathMaxDepth);
}
} else 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 = DomainTreeDescriptionProvider.SETTING + this.identityService.getId(entity) + DomainTreeDescriptionProvider.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, tree);
depthConsidered = Math.max(depthConsidered, childTreePathMaxDepth);
}
} else if (this.representationDataSearchService.existAnyRepresentationForTargetObjectId(treeItemId)) {
treeItemIdsToExpand.add(treeItemId);
depthConsidered = Math.max(depthConsidered, depth + 1);
}
}

return depthConsidered;
}

private Object getTreeItemObject(IEditingContext editingContext, Tree tree, String treeItemId) {
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 5a2801d

Please sign in to comment.