diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 5dd7644a8da..1b1633eca9d 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -59,6 +59,7 @@ As a result, the following maven modules have been deleted: `sirius-web-sample-a - https://github.com/eclipse-sirius/sirius-web/issues/3763[#3763] [core] updates some services behavior: ** The `org.eclipse.sirius.components.emf.services.DefaultIdentityService#getId(Object object)` Can now provides the Id if the Object is of type `org.eclipse.emf.ecore.resource.Resource`. Before this change, it would have returned null. ** The `org.eclipse.sirius.components.emf.services.DefaultLabelService` Can now provides the label if the Object is of type `org.eclipse.emf.ecore.resource.Resource`. Before this change, it would have returned an empty string. +** The `org.eclipse.sirius.components.emf.services.DefaultContentService#getContents(Object)` Can now provides the content if the Object is of type `org.eclipse.emf.ecore.resource.Resource`. Before this change, it would have returned an empty list. === Dependency update diff --git a/packages/emf/backend/sirius-components-emf/src/main/java/org/eclipse/sirius/components/emf/services/DefaultContentService.java b/packages/emf/backend/sirius-components-emf/src/main/java/org/eclipse/sirius/components/emf/services/DefaultContentService.java index a235bfa652d..1603a60e342 100644 --- a/packages/emf/backend/sirius-components-emf/src/main/java/org/eclipse/sirius/components/emf/services/DefaultContentService.java +++ b/packages/emf/backend/sirius-components-emf/src/main/java/org/eclipse/sirius/components/emf/services/DefaultContentService.java @@ -12,17 +12,17 @@ *******************************************************************************/ package org.eclipse.sirius.components.emf.services; -import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.provider.IEditingDomainItemProvider; import org.eclipse.sirius.components.core.api.IDefaultContentService; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; +import org.springframework.stereotype.Service; /** * Default implementation of {@link IDefaultContentService}. @@ -48,6 +48,10 @@ public List getContents(Object object) { contents.addAll(eObject.eContents()); } } + else if (object instanceof Resource resource) { + // The object may be a document + contents.addAll(resource.getContents()); + } return contents; } } diff --git a/packages/selection/backend/sirius-components-collaborative-selection/pom.xml b/packages/selection/backend/sirius-components-collaborative-selection/pom.xml index 2eb0182ab79..d666c78797c 100644 --- a/packages/selection/backend/sirius-components-collaborative-selection/pom.xml +++ b/packages/selection/backend/sirius-components-collaborative-selection/pom.xml @@ -75,6 +75,13 @@ assertj-core test + + org.eclipse.sirius + + sirius-components-collaborative-trees + + 2024.7.10 + diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogExpandAllTreePathProvider.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogExpandAllTreePathProvider.java new file mode 100644 index 00000000000..69c146d0ce9 --- /dev/null +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogExpandAllTreePathProvider.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * 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.collaborative.selection.services; + +import java.util.LinkedHashSet; +import java.util.Objects; +import java.util.Set; + +import org.eclipse.sirius.components.collaborative.selection.services.api.ISelectionDialogNavigationService; +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.representations.VariableManager; +import org.eclipse.sirius.components.trees.Tree; +import org.eclipse.sirius.components.trees.description.TreeDescription; +import org.springframework.stereotype.Service; + +/** + * Implementation of {@link IExpandAllTreePathProvider} for the Selection Dialog Tree. + * + * @author frouene + * @author fbarbin + */ +@Service +public class SelectionDialogExpandAllTreePathProvider implements IExpandAllTreePathProvider { + + private final IIdentityService identityService; + + private final IContentService contentService; + + private final ISelectionDialogNavigationService selectionDialogNavigationService; + + private final IRepresentationDescriptionSearchService representationDescriptionSearchService; + + public SelectionDialogExpandAllTreePathProvider(IIdentityService identityService, IContentService contentService, ISelectionDialogNavigationService selectionDialogNavigationService, IRepresentationDescriptionSearchService representationDescriptionSearchService) { + this.identityService = Objects.requireNonNull(identityService); + this.contentService = Objects.requireNonNull(contentService); + this.selectionDialogNavigationService = Objects.requireNonNull(selectionDialogNavigationService); + this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService); + } + + @Override + public boolean canHandle(Tree tree) { + return tree.getDescriptionId().startsWith(ISelectionDialogNavigationService.SELECTION_DIALOG_TREE_DESCRIPTION_KIND); + } + + @Override + public IPayload handle(IEditingContext editingContext, Tree tree, ExpandAllTreePathInput input) { + int maxDepth = 0; + String treeItemId = input.treeItemId(); + Set treeItemIdsToExpand = new LinkedHashSet<>(); + var object = this.getTreeItemObject(editingContext, treeItemId, tree); + if (object != null) { + // We need to get the current depth of the tree item + var itemAncestors = this.selectionDialogNavigationService.getAncestors(editingContext, treeItemId, tree); + 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 treeItemIdsToExpand, Tree tree) { + var depthConsidered = depth; + var object = this.getTreeItemObject(editingContext, treeItemId, tree); + if (object != null) { + var contents = this.contentService.getContents(object); + 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); + } + } + } + + 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; + } +} diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogNavigationService.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogNavigationService.java new file mode 100644 index 00000000000..0206beb01c3 --- /dev/null +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogNavigationService.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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.collaborative.selection.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.selection.services.api.ISelectionDialogNavigationService; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService; +import org.eclipse.sirius.components.representations.VariableManager; +import org.eclipse.sirius.components.trees.Tree; +import org.eclipse.sirius.components.trees.description.TreeDescription; +import org.springframework.stereotype.Service; + +/** + * Services for the navigation through the Selection Dialog Tree. + * + * @author frouene + * @author fbarbin + */ +@Service +public class SelectionDialogNavigationService implements ISelectionDialogNavigationService { + + private final IObjectService objectService; + + private final IRepresentationDescriptionSearchService representationDescriptionSearchService; + + public SelectionDialogNavigationService(IObjectService objectService, IRepresentationDescriptionSearchService representationDescriptionSearchService) { + this.objectService = Objects.requireNonNull(objectService); + this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService); + } + + @Override + public List getAncestors(IEditingContext editingContext, String treeItemId, Tree tree) { + List ancestorsIds = new ArrayList<>(); + + Optional optionalObject = this.getParentSemanticObject(treeItemId, ancestorsIds, editingContext, tree); + while (optionalObject.isPresent()) { + String parentId = this.objectService.getId(optionalObject.get()); + ancestorsIds.add(parentId); + optionalObject = this.getParentSemanticObject(parentId, ancestorsIds, editingContext, tree); + } + return ancestorsIds; + } + + private Optional getParentSemanticObject(String elementId, List ancestorsIds, IEditingContext editingContext, Tree tree) { + Optional result = Optional.empty(); + + var variableManager = new VariableManager(); + var optionalSemanticObject = this.getTreeItemObject(editingContext, elementId, tree); + var optionalTreeDescription = this.representationDescriptionSearchService.findById(editingContext, tree.getDescriptionId()) + .filter(TreeDescription.class::isInstance) + .map(TreeDescription.class::cast); + + if (optionalSemanticObject.isPresent() && optionalTreeDescription.isPresent()) { + variableManager.put(VariableManager.SELF, optionalSemanticObject.get()); + variableManager.put(TreeDescription.ID, elementId); + variableManager.put(IEditingContext.EDITING_CONTEXT, editingContext); + result = Optional.ofNullable(optionalTreeDescription.get().getParentObjectProvider().apply(variableManager)); + } + return result; + } + + private Optional getTreeItemObject(IEditingContext editingContext, String id, 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, id); + return Optional.ofNullable(optionalTreeDescription.get().getTreeItemObjectProvider().apply(variableManager)); + } + return Optional.empty(); + } +} diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogTreePathProvider.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogTreePathProvider.java new file mode 100644 index 00000000000..739121ccccd --- /dev/null +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/SelectionDialogTreePathProvider.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.components.collaborative.selection.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +import org.eclipse.sirius.components.collaborative.selection.services.api.ISelectionDialogNavigationService; +import org.eclipse.sirius.components.collaborative.trees.api.ITreePathProvider; +import org.eclipse.sirius.components.collaborative.trees.dto.TreePath; +import org.eclipse.sirius.components.collaborative.trees.dto.TreePathInput; +import org.eclipse.sirius.components.collaborative.trees.dto.TreePathSuccessPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.trees.Tree; +import org.springframework.stereotype.Service; + +/** + * ITreePathProvider implementation for the Selection Dialog tree. + * + * @author pcdavid + * @author fbarbin + */ +@Service +public class SelectionDialogTreePathProvider implements ITreePathProvider { + + private final ISelectionDialogNavigationService selectionDialogNavigationService; + + public SelectionDialogTreePathProvider(ISelectionDialogNavigationService selectionDialogNavigationService) { + this.selectionDialogNavigationService = Objects.requireNonNull(selectionDialogNavigationService); + } + + @Override + public boolean canHandle(Tree tree) { + return tree != null && tree.getDescriptionId().startsWith(ISelectionDialogNavigationService.SELECTION_DIALOG_TREE_DESCRIPTION_KIND); + } + + @Override + public IPayload handle(IEditingContext editingContext, Tree tree, TreePathInput input) { + int maxDepth = 0; + Set allAncestors = new LinkedHashSet<>(); + for (String selectionEntryId : input.selectionEntryIds()) { + List itemAncestors = this.selectionDialogNavigationService.getAncestors(editingContext, selectionEntryId, tree); + allAncestors.addAll(itemAncestors); + maxDepth = Math.max(maxDepth, itemAncestors.size()); + } + return new TreePathSuccessPayload(input.id(), new TreePath(allAncestors.stream().toList(), maxDepth)); + } + +} diff --git a/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/api/ISelectionDialogNavigationService.java b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/api/ISelectionDialogNavigationService.java new file mode 100644 index 00000000000..db3f5794358 --- /dev/null +++ b/packages/selection/backend/sirius-components-collaborative-selection/src/main/java/org/eclipse/sirius/components/collaborative/selection/services/api/ISelectionDialogNavigationService.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.collaborative.selection.services.api; + +import java.util.List; + +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.trees.Tree; + +/** + * Interface of the service for the navigation through the Selection Dialog Tree. + * + * @author fbarbin + */ +public interface ISelectionDialogNavigationService { + + String SELECTION_DIALOG_TREE_DESCRIPTION_KIND = "siriusComponents://selectionDialogTreeDescription"; + + List getAncestors(IEditingContext editingContext, String treeItemId, Tree tree); + + /** + * Implementation which does nothing, used for mocks in unit tests. + * + * @author fbarbin + */ + class NoOp implements ISelectionDialogNavigationService { + + @Override + public List getAncestors(IEditingContext editingContext, String treeItemId, Tree tree) { + return List.of(); + } + } + +} diff --git a/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx b/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx index 2aca1c4fb0f..de3226cfa42 100644 --- a/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx +++ b/packages/selection/frontend/sirius-components-selection/src/SelectionDialog.tsx @@ -73,8 +73,8 @@ export const SelectionDialog = ({ enableMultiSelection={true} synchronizedWithSelection={true} activeFilterIds={[]} - textToFilter={null} - textToHighlight={null} + textToFilter={''} + textToHighlight={''} treeItemActionRender={(props) => } /> ); diff --git a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/api/SelectionDialogDescriptionConverter.java b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/api/SelectionDialogDescriptionConverter.java index 706ddc6e2f6..09562fe0a04 100644 --- a/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/api/SelectionDialogDescriptionConverter.java +++ b/packages/view/backend/sirius-components-view-emf/src/main/java/org/eclipse/sirius/components/view/emf/api/SelectionDialogDescriptionConverter.java @@ -20,10 +20,15 @@ import java.util.function.Function; import java.util.function.Predicate; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IObjectService; import org.eclipse.sirius.components.core.api.IURLParser; import org.eclipse.sirius.components.core.api.labels.StyledString; +import org.eclipse.sirius.components.emf.services.JSONResourceFactory; +import org.eclipse.sirius.components.emf.services.api.IEMFEditingContext; import org.eclipse.sirius.components.interpreter.AQLInterpreter; import org.eclipse.sirius.components.interpreter.Result; import org.eclipse.sirius.components.representations.Failure; @@ -32,6 +37,7 @@ import org.eclipse.sirius.components.representations.VariableManager; import org.eclipse.sirius.components.selection.description.SelectionDescription; import org.eclipse.sirius.components.trees.description.TreeDescription; +import org.eclipse.sirius.components.trees.renderer.TreeRenderer; import org.eclipse.sirius.components.view.diagram.DialogDescription; import org.eclipse.sirius.components.view.diagram.SelectionDialogDescription; import org.eclipse.sirius.components.view.diagram.SelectionDialogTreeDescription; @@ -116,21 +122,8 @@ private TreeDescription createTreeDescription(SelectionDialogDescription selecti SelectionDialogTreeDescription selectionDialogTreeDescription = selectionDescription.getSelectionDialogTreeDescription(); final String treeDescriptionId = this.diagramIdProvider.getId(selectionDialogTreeDescription); - Function> childrenProvider = this.getChildrenProvider(interpreter, selectionDialogTreeDescription); - Function> elementsProvider = this.getElementProvider(interpreter, selectionDialogTreeDescription); - Function hasChildrenProvider = variableManager -> { - String childrenExpression = selectionDialogTreeDescription.getChildrenExpression(); - String safeExpression = Optional.ofNullable(childrenExpression).orElse(""); - if (safeExpression.isBlank()) { - return false; - } else { - Result result = interpreter.evaluateExpression(variableManager.getVariables(), safeExpression); - return !result.asObjects().orElse(List.of()).isEmpty(); - } - }; - Function deleteHandler = variableManager -> new Failure("Unexecutable delete handler"); BiFunction renameHandler = (variableManager, newValue) -> new Failure("Unexecutable rename handler"); @@ -174,6 +167,11 @@ private TreeDescription createTreeDescription(SelectionDialogDescription selecti .orElse(false); }; + + Function> childrenProvider = variableManager -> this.getChildren(variableManager, interpreter, selectionDialogTreeDescription, isSelectableProvider); + + Function hasChildrenProvider = variableManager -> this.hasChildren(interpreter, selectionDialogTreeDescription, variableManager, isSelectableProvider); + Predicate canCreatePredicate = variableManager -> { return variableManager.get(TREE_ID, String.class) .filter(id -> id.startsWith(SELECTION_PREFIX)) @@ -201,35 +199,106 @@ private TreeDescription createTreeDescription(SelectionDialogDescription selecti .iconURLProvider(imageURLProvider) .selectableProvider(isSelectableProvider) .treeItemObjectProvider(this::getTreeItemObject) - .parentObjectProvider(variableManager -> null) + .parentObjectProvider(this::getParentObject) .build(); } + private Boolean hasChildren(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription, VariableManager variableManager, Function isSelectableProvider) { + boolean hasChildren = false; + Object self = variableManager.getVariables().get(VariableManager.SELF); + hasChildren = !this.computeChildrenFromExpression(variableManager, interpreter, selectionDialogTreeDescription).isEmpty(); + return hasChildren && this.hasCompatibleDescendants(interpreter, selectionDialogTreeDescription, variableManager, self, false, isSelectableProvider); + } + + private boolean hasCompatibleDescendants(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription, VariableManager variableManager, Object object, boolean isDescendant, Function isSelectableProvider) { + VariableManager childVariableManager = variableManager.createChild(); + childVariableManager.put(VariableManager.SELF, object); + return isDescendant && isSelectableProvider.apply(childVariableManager) + || this.computeChildrenFromExpression(variableManager, interpreter, selectionDialogTreeDescription).stream().anyMatch(eContent -> this.hasCompatibleDescendants(interpreter, selectionDialogTreeDescription, childVariableManager, eContent, true, isSelectableProvider)); + } + private Object getTreeItemObject(VariableManager variableManager) { + Object result = null; 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()); + var optionalObject = this.objectService.getObject(optionalEditingContext.get(), optionalId.get()); + if (optionalObject.isPresent()) { + result = optionalObject.get(); + } else { + var optionalEditingDomain = Optional.of(optionalEditingContext.get()) + .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(optionalId.get()); + + result = resourceSet.getResources().stream() + .filter(resource -> resource.getURI().equals(uri)). + findFirst() + .orElse(null); + } + } } - return null; + + return result; } - private Function> getChildrenProvider(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription) { - return variableManager -> { - String childrenExpression = selectionDialogTreeDescription.getChildrenExpression(); - String safeExpression = Optional.ofNullable(childrenExpression).orElse(""); - if (safeExpression.isBlank()) { - return List.of(); + + private Object getParentObject(VariableManager variableManager) { + Object result = null; + Object self = variableManager.getVariables().get(VariableManager.SELF); + if (self instanceof EObject eObject) { + Object semanticContainer = eObject.eContainer(); + if (semanticContainer == null) { + semanticContainer = eObject.eResource(); } - else { - Result result = interpreter.evaluateExpression(variableManager.getVariables(), safeExpression); - return result.asObjects() - .orElse(List.of()) - .stream() - .filter(Objects::nonNull) - .toList(); + result = semanticContainer; + } + return result; + } + + private List getChildren(VariableManager variableManager, AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription, Function isSelectableProvider) { + List result = new ArrayList<>(); + + List expandedIds = new ArrayList<>(); + Object objects = variableManager.getVariables().get(TreeRenderer.EXPANDED); + if (objects instanceof List list) { + expandedIds = list.stream().filter(String.class::isInstance).map(String.class::cast).toList(); + } + + String id = this.getTreeItemId(variableManager); + if (expandedIds.contains(id)) { + result.addAll(this.computeChildrenFromExpression(variableManager, interpreter, selectionDialogTreeDescription)); + } + result.removeIf(object -> { + if (object instanceof EObject eObject) { + VariableManager childVariableManager = variableManager.createChild(); + childVariableManager.put(VariableManager.SELF, eObject); + return !isSelectableProvider.apply(childVariableManager) && !this.hasChildren(interpreter, selectionDialogTreeDescription, childVariableManager, isSelectableProvider); + } else { + return false; } - }; + }); + return result; + } + + private List computeChildrenFromExpression(VariableManager variableManager, AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription) { + List result = new ArrayList<>(); + String childrenExpression = selectionDialogTreeDescription.getChildrenExpression(); + String safeExpression = Optional.ofNullable(childrenExpression).orElse(""); + if (!safeExpression.isBlank()) { + Result interpreterResult = interpreter.evaluateExpression(variableManager.getVariables(), safeExpression); + result = interpreterResult.asObjects() + .orElse(List.of()) + .stream() + .filter(Objects::nonNull) + .toList(); + } + return result; } private Function> getElementProvider(AQLInterpreter interpreter, SelectionDialogTreeDescription selectionDialogTreeDescription) { @@ -260,4 +329,13 @@ private Optional getTargetObjectId(VariableManager variableManager) { .map(parameters -> parameters.get(TARGET_OBJECT_ID).get(0)); } + private String getTreeItemId(VariableManager variableManager) { + Object self = variableManager.getVariables().get(VariableManager.SELF); + String id = null; + if (self != null) { + id = this.objectService.getId(self); + } + return id; + } + }