diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssert.java deleted file mode 100644 index 08665a6876..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssert.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 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.components.forms.tests; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.sirius.components.forms.tests.FormAssertions.assertThat; - -import java.util.ArrayList; -import java.util.List; - -import org.assertj.core.api.AbstractAssert; -import org.eclipse.sirius.components.forms.AbstractWidget; -import org.eclipse.sirius.components.forms.Form; -import org.eclipse.sirius.components.forms.Group; -import org.eclipse.sirius.components.forms.Page; - -/** - * Custom assertion class used to performs some tests on a form. - * - * @author lfasani - */ -public class FormAssert extends AbstractAssert { - - public FormAssert(Form form) { - super(form, FormAssert.class); - } - - /** - * Asserts that the actual form has the same properties as the given form (without taking into account the position - * and size of any elements. - * - * @param form - * The given form - * @param idPolicy - * Indicates if the identifiers of the form elements should match too - * @return The current form assert - */ - public FormAssert matchesRecursively(Form form, IdPolicy idPolicy) { - this.matches(form, idPolicy); - - if (this.actual != null && form != null) { - assertThat(this.actual.getPages()).hasSize(form.getPages().size()); - - if (this.actual.getPages().size() == form.getPages().size()) { - int size = this.actual.getPages().size(); - for (int i = 0; i < size; i++) { - Page actualPage = this.actual.getPages().get(i); - Page page = form.getPages().get(i); - assertThat(actualPage).matchesRecursively(page, idPolicy); - } - } - } - - return this; - } - - /** - * Asserts that the actual form has the same properties as the given form. - * - * @param form - * The given form - * @param idPolicy - * Indicates if the identifiers of the form elements should match too - * @return The current form assert - */ - public FormAssert matches(Form form, IdPolicy idPolicy) { - if (form != null) { - this.isNotNull(); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(this.actual.getId()).isEqualTo(form.getId()); - } - - assertThat(this.actual.getLabel()).isEqualTo(form.getLabel()); - } else { - this.isNull(); - } - - return this; - } - - public void isValid() { - this.isNotNull(); - - List ids = new ArrayList<>(); - this.actual.getPages().forEach(page -> this.visitPageId(ids, page)); - } - - private void visitPageId(List ids, Page page) { - if (ids.contains(page.getId())) { - this.failWithMessage("The id of the page <%s> already exists in the form", page.getId()); - } - ids.add(page.getId()); - - page.getGroups().forEach(group -> this.visitGroupId(ids, group)); - } - - private void visitGroupId(List ids, Group group) { - if (ids.contains(group.getId())) { - this.failWithMessage("The id of the group <%s> already exists in the form", group.getId()); - } - ids.add(group.getId()); - - group.getWidgets().forEach(widget -> this.visitWidgetId(ids, widget)); - } - - private void visitWidgetId(List ids, AbstractWidget widget) { - if (widget != null) { - if (ids.contains(widget.getId())) { - this.failWithMessage("The id of the widget <%s> already exists in the form", widget.getId()); - } - ids.add(widget.getId()); - } - } -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssertions.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssertions.java deleted file mode 100644 index d4c8b88d8a..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/FormAssertions.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020 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.forms.tests; - -import org.assertj.core.api.Assertions; -import org.eclipse.sirius.components.forms.AbstractWidget; -import org.eclipse.sirius.components.forms.Form; -import org.eclipse.sirius.components.forms.Group; -import org.eclipse.sirius.components.forms.ListItem; -import org.eclipse.sirius.components.forms.Page; - -/** - * Entry point of all the AssertJ assertions with the form specific ones too. - * - * @author lfasani - */ -public class FormAssertions extends Assertions { - public static FormAssert assertThat(Form form) { - return new FormAssert(form); - } - - public static PageAssert assertThat(Page page) { - return new PageAssert(page); - } - - public static GroupAssert assertThat(Group group) { - return new GroupAssert(group); - } - - public static WidgetAssert assertThat(AbstractWidget widget) { - return new WidgetAssert(widget); - } - - public static ListItemAssert assertThat(ListItem listItem) { - return new ListItemAssert(listItem); - } -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/GroupAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/GroupAssert.java deleted file mode 100644 index e5118410b1..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/GroupAssert.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020 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.forms.tests; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.sirius.components.forms.tests.FormAssertions.assertThat; - -import org.assertj.core.api.AbstractAssert; -import org.eclipse.sirius.components.forms.AbstractWidget; -import org.eclipse.sirius.components.forms.Group; - -/** - * Custom assertion class used to perform some tests on a group. - * - * @author lfasani - */ -public class GroupAssert extends AbstractAssert { - - public GroupAssert(Group group) { - super(group, GroupAssert.class); - } - - public GroupAssert matchesRecursively(Group group, IdPolicy idPolicy) { - this.isNotNull(); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(this.actual.getId()).isEqualTo(group.getId()); - } - - assertThat(this.actual.getLabel()).isEqualTo(group.getLabel()); - - if (this.actual.getWidgets().size() == group.getWidgets().size()) { - int size = this.actual.getWidgets().size(); - for (int i = 0; i < size; i++) { - AbstractWidget actualWidget = this.actual.getWidgets().get(i); - AbstractWidget widget = group.getWidgets().get(i); - assertThat(actualWidget).matches(widget, idPolicy); - } - } - - return this; - } - -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/ListItemAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/ListItemAssert.java deleted file mode 100644 index ccbdadbc60..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/ListItemAssert.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020 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.forms.tests; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.assertj.core.api.AbstractAssert; -import org.eclipse.sirius.components.forms.ListItem; - -/** - * Custom assertion class used to perform some tests on a ListItem. - * - * @author lfasani - */ -public class ListItemAssert extends AbstractAssert { - - public ListItemAssert(ListItem actual) { - super(actual, ListItemAssert.class); - } - - public ListItemAssert matches(ListItem listItem, IdPolicy idPolicy) { - this.isNotNull(); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(this.actual.getId()).isEqualTo(listItem.getId()); - } - - assertThat(this.actual.getLabel()).isEqualTo(listItem.getLabel()); - - return this; - } - -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/PageAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/PageAssert.java deleted file mode 100644 index b25bc41661..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/PageAssert.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020 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.forms.tests; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.eclipse.sirius.components.forms.tests.FormAssertions.assertThat; - -import org.assertj.core.api.AbstractAssert; -import org.eclipse.sirius.components.forms.Group; -import org.eclipse.sirius.components.forms.Page; - -/** - * Custom assertion class used to perform some tests on a page. - * - * @author lfasani - */ -public class PageAssert extends AbstractAssert { - public PageAssert(Page page) { - super(page, PageAssert.class); - } - - public PageAssert matchesRecursively(Page page, IdPolicy idPolicy) { - if (page != null) { - this.isNotNull(); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(this.actual.getId()).isEqualTo(page.getId()); - } - - assertThat(this.actual.getLabel()).isEqualTo(page.getLabel()); - - if (this.actual.getGroups().size() == page.getGroups().size()) { - int size = this.actual.getGroups().size(); - for (int i = 0; i < size; i++) { - Group actualGroup = this.actual.getGroups().get(i); - Group group = page.getGroups().get(i); - assertThat(actualGroup).matchesRecursively(group, idPolicy); - } - } - } - - return this; - } -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetAssert.java deleted file mode 100644 index c87d9a32a4..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetAssert.java +++ /dev/null @@ -1,168 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2023 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.forms.tests; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatObject; -import static org.eclipse.sirius.components.forms.tests.FormAssertions.assertThat; - -import java.util.HashMap; -import java.util.Map; - -import org.assertj.core.api.AbstractAssert; -import org.eclipse.sirius.components.forms.AbstractWidget; -import org.eclipse.sirius.components.forms.Checkbox; -import org.eclipse.sirius.components.forms.List; -import org.eclipse.sirius.components.forms.ListItem; -import org.eclipse.sirius.components.forms.Radio; -import org.eclipse.sirius.components.forms.RadioOption; -import org.eclipse.sirius.components.forms.Select; -import org.eclipse.sirius.components.forms.SelectOption; -import org.eclipse.sirius.components.forms.Textarea; -import org.eclipse.sirius.components.forms.Textfield; -import org.eclipse.sirius.components.forms.TreeNode; -import org.eclipse.sirius.components.forms.TreeWidget; - -/** - * Custom assertion class used to perform some tests on a widget. - * - * @author lfasani - */ -public class WidgetAssert extends AbstractAssert { - - public WidgetAssert(AbstractWidget actual) { - super(actual, WidgetAssert.class); - } - - public WidgetAssert matches(AbstractWidget widget, IdPolicy idPolicy) { - this.isNotNull(); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(this.actual.getId()).isEqualTo(widget.getId()); - } - - if (this.actual instanceof List actualList && widget instanceof List list) { - assertThat(actualList.getLabel()).isEqualTo(list.getLabel()); - assertThat(actualList.getItems()).hasSameSizeAs(list.getItems()); - - int size = actualList.getItems().size(); - for (int i = 0; i < size; i++) { - ListItem actualListItem = actualList.getItems().get(i); - ListItem listItem = list.getItems().get(i); - assertThat(actualListItem).matches(listItem, idPolicy); - } - } else if (this.actual instanceof Checkbox actualCheckbox && widget instanceof Checkbox checkbox) { - assertThat(actualCheckbox.getLabel()).isEqualTo(checkbox.getLabel()); - assertThat(actualCheckbox.isValue()).isEqualTo(checkbox.isValue()); - } else if (this.actual instanceof Radio && widget instanceof Radio) { - this.assertRadio((Radio) this.actual, (Radio) widget, idPolicy); - } else if (this.actual instanceof Select && widget instanceof Select) { - this.assertSelect((Select) this.actual, (Select) widget, idPolicy); - } else if (this.actual instanceof TreeWidget && widget instanceof TreeWidget) { - this.assertTree((TreeWidget) this.actual, (TreeWidget) widget, idPolicy); - } else if (this.actual instanceof Textarea actualTextarea && widget instanceof Textarea textarea) { - assertThat(actualTextarea.getLabel()).isEqualTo(textarea.getLabel()); - assertThat(actualTextarea.getValue()).isEqualTo(textarea.getValue()); - } else if (this.actual instanceof Textfield actualTextfield && widget instanceof Textfield textfield) { - assertThat(actualTextfield.getLabel()).isEqualTo(textfield.getLabel()); - assertThat(actualTextfield.getValue()).isEqualTo(textfield.getValue()); - } - - return this; - } - - private void assertSelect(Select actualSelect, Select select, IdPolicy idPolicy) { - assertThat(actualSelect.getLabel()).isEqualTo(select.getLabel()); - assertThat(actualSelect.getOptions()).hasSameSizeAs(select.getOptions()); - - int size = actualSelect.getOptions().size(); - for (int i = 0; i < size; i++) { - SelectOption actualSelectOption = actualSelect.getOptions().get(i); - SelectOption selectOption = select.getOptions().get(i); - - assertThatObject(actualSelectOption).isNotNull(); - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(actualSelectOption.getId()).isEqualTo(selectOption.getId()); - } - assertThat(actualSelectOption.getLabel()).isEqualTo(selectOption.getLabel()); - } - } - - private void assertRadio(Radio actualRadio, Radio radio, IdPolicy idPolicy) { - assertThat(actualRadio.getLabel()).isEqualTo(radio.getLabel()); - assertThat(actualRadio.getOptions()).hasSameSizeAs(radio.getOptions()); - - int size = actualRadio.getOptions().size(); - for (int i = 0; i < size; i++) { - RadioOption actualRadioOption = actualRadio.getOptions().get(i); - RadioOption radioOption = radio.getOptions().get(i); - - assertThatObject(actualRadioOption).isNotNull(); - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(actualRadioOption.getId()).isEqualTo(radioOption.getId()); - } - assertThat(actualRadioOption.getLabel()).isEqualTo(radioOption.getLabel()); - assertThat(actualRadioOption.isSelected()).isEqualTo(radioOption.isSelected()); - } - } - - private void assertTree(TreeWidget actualTree, TreeWidget expectedTree, IdPolicy idPolicy) { - assertThat(actualTree.getLabel()).isEqualTo(expectedTree.getLabel()); - assertThat(actualTree.getNodes()).hasSameSizeAs(expectedTree.getNodes()); - assertThat(actualTree.getExpandedNodesIds()).hasSameSizeAs(expectedTree.getExpandedNodesIds()); - - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(actualTree.getExpandedNodesIds()).hasSameElementsAs(expectedTree.getExpandedNodesIds()); - } - - int size = actualTree.getNodes().size(); - for (int i = 0; i < size; i++) { - TreeNode actualNode = actualTree.getNodes().get(i); - TreeNode expectedNode = expectedTree.getNodes().get(i); - - assertThat(actualNode.getLabel()).isEqualTo(expectedNode.getLabel()); - assertThat(actualNode.getIconURL()).hasSameSizeAs(expectedNode.getIconURL()); - for (int j = 0; j < actualNode.getIconURL().size(); j++) { - assertThat("/api/images" + actualNode.getIconURL().get(j)).isEqualTo(expectedNode.getIconURL().get(j)); - } - assertThat(actualNode.getKind()).isEqualTo(expectedNode.getKind()); - if (idPolicy == IdPolicy.WITH_ID) { - assertThat(actualNode.getId()).isEqualTo(expectedNode.getId()); - } - } - if (idPolicy == IdPolicy.WITHOUT_ID) { - // Even if we do not test that nodes have the same id equality, we need to check that the logically - // equivalent nodes are expanded and have the same parent/child relationship. - Map expectedToActualIds = new HashMap<>(); - for (int i = 0; i < size; i++) { - TreeNode actualNode = actualTree.getNodes().get(i); - TreeNode expectedNode = expectedTree.getNodes().get(i); - expectedToActualIds.put(expectedNode.getId(), actualNode.getId()); - } - - // @formatter:off - assertThat(actualTree.getExpandedNodesIds()) - .containsAll(expectedTree.getExpandedNodesIds().stream().map(expectedToActualIds::get).toList()); - // @formatter:on - - for (int i = 0; i < size; i++) { - TreeNode actualNode = actualTree.getNodes().get(i); - TreeNode expectedNode = expectedTree.getNodes().get(i); - assertThat(actualNode.getId()).isEqualTo(expectedToActualIds.get(expectedNode.getId())); - assertThat(actualNode.getParentId()).isEqualTo(expectedToActualIds.get(expectedNode.getParentId())); - } - } - - } - -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetDeserializer.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetDeserializer.java deleted file mode 100644 index 69048c0ff1..0000000000 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/WidgetDeserializer.java +++ /dev/null @@ -1,81 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019, 2020, 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.components.forms.tests; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.ObjectCodec; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import java.io.IOException; - -import org.eclipse.sirius.components.forms.AbstractWidget; -import org.eclipse.sirius.components.forms.Checkbox; -import org.eclipse.sirius.components.forms.List; -import org.eclipse.sirius.components.forms.Radio; -import org.eclipse.sirius.components.forms.Select; -import org.eclipse.sirius.components.forms.Textarea; -import org.eclipse.sirius.components.forms.Textfield; -import org.eclipse.sirius.components.forms.TreeWidget; - -/** - * Custom deserializer for AbstractWidget since Jackson need to know how to find the concrete class matching the JSON - * data. - * - * @author lfasani - */ -public class WidgetDeserializer extends StdDeserializer { - - private static final long serialVersionUID = 5722074461929397488L; - - public WidgetDeserializer() { - this(null); - } - - public WidgetDeserializer(Class valueClass) { - super(valueClass); - } - - @Override - public AbstractWidget deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { - AbstractWidget nodeStyle = null; - ObjectCodec objectCodec = jsonParser.getCodec(); - if (objectCodec instanceof ObjectMapper) { - ObjectMapper mapper = (ObjectMapper) objectCodec; - ObjectNode root = mapper.readTree(jsonParser); - - JsonNode typeName = root.get("__typename"); - if (Radio.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), Radio.class); - } else if (Select.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), Select.class); - } else if (Checkbox.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), Checkbox.class); - } else if (Textarea.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), Textarea.class); - } else if (Textfield.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), Textfield.class); - } else if (List.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), List.class); - } else if (TreeWidget.class.getSimpleName().equals(typeName.asText())) { - nodeStyle = mapper.readValue(root.toString(), TreeWidget.class); - } - } - return nodeStyle; - } - -} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/CheckboxAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/CheckboxAssert.java new file mode 100644 index 0000000000..3faffedb56 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/CheckboxAssert.java @@ -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.components.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Checkbox; + +/** + * Custom assertion class used to perform some tests on a checkbox widget. + * + * @author sbegaudeau + */ +public class CheckboxAssert extends AbstractAssert { + + public CheckboxAssert(Checkbox checkbox) { + super(checkbox, CheckboxAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssert.java new file mode 100644 index 0000000000..44b0206d94 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssert.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2019, 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.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Form; + +/** + * Custom assertion class used to performs some tests on a form. + * + * @author lfasani + */ +public class FormAssert extends AbstractAssert { + + public FormAssert(Form form) { + super(form, FormAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssertions.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssertions.java new file mode 100644 index 0000000000..5ac82e96a5 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/FormAssertions.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2019, 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.forms.tests.assertions; + +import org.assertj.core.api.Assertions; +import org.eclipse.sirius.components.forms.Checkbox; +import org.eclipse.sirius.components.forms.Form; +import org.eclipse.sirius.components.forms.Group; +import org.eclipse.sirius.components.forms.MultiSelect; +import org.eclipse.sirius.components.forms.Page; +import org.eclipse.sirius.components.forms.RichText; +import org.eclipse.sirius.components.forms.Select; +import org.eclipse.sirius.components.forms.Textarea; +import org.eclipse.sirius.components.forms.Textfield; +import org.eclipse.sirius.components.forms.TreeWidget; + +/** + * Entry point of all the AssertJ assertions with the form specific ones too. + * + * @author lfasani + */ +public class FormAssertions extends Assertions { + public static FormAssert assertThat(Form form) { + return new FormAssert(form); + } + + public static PageAssert assertThat(Page page) { + return new PageAssert(page); + } + + public static GroupAssert assertThat(Group group) { + return new GroupAssert(group); + } + + public static CheckboxAssert assertThat(Checkbox checkbox) { + return new CheckboxAssert(checkbox); + } + + public static MultiSelectAssert assertThat(MultiSelect multiSelect) { + return new MultiSelectAssert(multiSelect); + } + + public static RichTextAssert assertThat(RichText richText) { + return new RichTextAssert(richText); + } + + public static SelectAssert assertThat(Select select) { + return new SelectAssert(select); + } + + public static TextareaAssert assertThat(Textarea textarea) { + return new TextareaAssert(textarea); + } + + public static TextfieldAssert assertThat(Textfield textfield) { + return new TextfieldAssert(textfield); + } + + public static TreeWidgetAssert assertThat(TreeWidget treeWidget) { + return new TreeWidgetAssert(treeWidget); + } + +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/GroupAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/GroupAssert.java new file mode 100644 index 0000000000..9841f022b6 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/GroupAssert.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2019, 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.forms.tests.assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Group; +import org.eclipse.sirius.components.forms.GroupDisplayMode; + +/** + * Custom assertion class used to perform some tests on a group. + * + * @author lfasani + */ +public class GroupAssert extends AbstractAssert { + + public GroupAssert(Group group) { + super(group, GroupAssert.class); + } + + public GroupAssert hasDisplayMode(GroupDisplayMode groupDisplayMode) { + assertThat(this.actual.getDisplayMode()).isEqualTo(groupDisplayMode); + return this; + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/MultiSelectAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/MultiSelectAssert.java new file mode 100644 index 0000000000..ed60cf8cb2 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/MultiSelectAssert.java @@ -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.components.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.MultiSelect; + +/** + * Custom assertion class used to perform some tests on a multi-select widget. + * + * @author sbegaudeau + */ +public class MultiSelectAssert extends AbstractAssert { + + public MultiSelectAssert(MultiSelect multiSelect) { + super(multiSelect, MultiSelectAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/PageAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/PageAssert.java new file mode 100644 index 0000000000..afe2e10a56 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/PageAssert.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2019, 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.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Page; + +/** + * Custom assertion class used to perform some tests on a page. + * + * @author lfasani + */ +public class PageAssert extends AbstractAssert { + public PageAssert(Page page) { + super(page, PageAssert.class); + } + +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/RichTextAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/RichTextAssert.java new file mode 100644 index 0000000000..f753ec5f16 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/RichTextAssert.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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.forms.tests.assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.RichText; + +/** + * Custom assertion class used to perform some tests on a rich text widget. + * + * @author sbegaudeau + */ +public class RichTextAssert extends AbstractAssert { + + public RichTextAssert(RichText richText) { + super(richText, RichTextAssert.class); + } + + public RichTextAssert hasValue(String value) { + assertThat(this.actual.getValue()).isEqualTo(value); + return this; + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/SelectAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/SelectAssert.java new file mode 100644 index 0000000000..5be4ab87eb --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/SelectAssert.java @@ -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.components.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Select; + +/** + * Custom assertion class used to perform some tests on a select widget. + * + * @author sbegaudeau + */ +public class SelectAssert extends AbstractAssert { + + public SelectAssert(Select select) { + super(select, SelectAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextareaAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextareaAssert.java new file mode 100644 index 0000000000..b64df31b9f --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextareaAssert.java @@ -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.components.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Textarea; + +/** + * Custom assertion class used to perform some tests on a textarea widget. + * + * @author sbegaudeau + */ +public class TextareaAssert extends AbstractAssert { + + public TextareaAssert(Textarea textarea) { + super(textarea, TextareaAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextfieldAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextfieldAssert.java new file mode 100644 index 0000000000..245586a1fe --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TextfieldAssert.java @@ -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.components.forms.tests.assertions; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.Textfield; + +/** + * Custom assertion class used to perform some tests on a textfield widget. + * + * @author sbegaudeau + */ +public class TextfieldAssert extends AbstractAssert { + + public TextfieldAssert(Textfield textfield) { + super(textfield, TextareaAssert.class); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TreeWidgetAssert.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TreeWidgetAssert.java new file mode 100644 index 0000000000..6833c57815 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/assertions/TreeWidgetAssert.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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.forms.tests.assertions; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.assertj.core.api.AbstractAssert; +import org.eclipse.sirius.components.forms.TreeNode; +import org.eclipse.sirius.components.forms.TreeWidget; + +/** + * Custom assertion class used to perform some tests on a tree widget. + * + * @author sbegaudeau + */ +public class TreeWidgetAssert extends AbstractAssert { + + public TreeWidgetAssert(TreeWidget treeWidget) { + super(treeWidget, TreeWidgetAssert.class); + } + + public TreeWidgetAssert hasCheckedTreeItemsSize(int size) { + var checkedTreeNodesCount = this.actual.getNodes().stream() + .filter(TreeNode::isValue) + .count(); + assertThat(checkedTreeNodesCount) + .withFailMessage("Expecting %d checked tree items but found %d instead", size, checkedTreeNodesCount) + .isEqualTo(size); + + return this; + } + + public TreeWidgetAssert hasTreeItemWithLabel(String label) { + var hasTreeItemWithLabel = this.actual.getNodes().stream() + .anyMatch(treeNode -> treeNode.getLabel().equals(label)); + assertThat(hasTreeItemWithLabel) + .withFailMessage("Expecting at least one tree item with the label \"" + label + "\" but none has been found") + .isTrue(); + + return this; + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/FormNavigator.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/FormNavigator.java new file mode 100644 index 0000000000..c455627c34 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/FormNavigator.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2024, 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.forms.tests.navigation; + +import java.util.Objects; + +import org.eclipse.sirius.components.forms.Form; + +/** + * Entry point of the navigation in a form representation. + * + * @author sbegaudeau + */ +public class FormNavigator { + + private final Form form; + + public FormNavigator(Form form) { + this.form = Objects.requireNonNull(form); + } + + public PageNavigator page(String label) { + return this.form.getPages().stream() + .filter(page -> page.getLabel().equals(label)) + .findFirst() + .map(PageNavigator::new) + .orElseThrow(() -> new IllegalArgumentException("No page found with the given label \"" + label + "\"")); + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/GroupNavigator.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/GroupNavigator.java new file mode 100644 index 0000000000..1d19def0a1 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/GroupNavigator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2024, 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.forms.tests.navigation; + +import java.util.Objects; + +import org.eclipse.sirius.components.forms.AbstractWidget; +import org.eclipse.sirius.components.forms.Group; + +/** + * Used to navigate from a group. + * + * @author sbegaudeau + */ +public class GroupNavigator { + + private final Group group; + + public GroupNavigator(Group group) { + this.group = Objects.requireNonNull(group); + } + + public T findWidget(String label, Class clazz) { + return this.group.getWidgets().stream() + .filter(widget -> widget.getLabel().equals(label)) + .filter(clazz::isInstance) + .map(clazz::cast) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No widget found with the given label \"" + label + "\" and the given type \"" + clazz.getSimpleName() + "\"")); + } + + public Group getGroup() { + return this.group; + } +} diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/PageNavigator.java b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/PageNavigator.java new file mode 100644 index 0000000000..bf228dbc43 --- /dev/null +++ b/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/navigation/PageNavigator.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2024, 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.forms.tests.navigation; + +import java.util.Objects; + +import org.eclipse.sirius.components.forms.Page; + +/** + * Used to navigate from a page. + * + * @author sbegaudeau + */ +public class PageNavigator { + + private final Page page; + + public PageNavigator(Page page) { + this.page = Objects.requireNonNull(page); + } + + public GroupNavigator group(String label) { + return this.page.getGroups().stream() + .filter(group -> group.getLabel().equals(label)) + .findFirst() + .map(GroupNavigator::new) + .orElseThrow(() -> new IllegalArgumentException("No group found with the given label \"" + label + "\"")); + } + + public Page getPage() { + return this.page; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/pom.xml b/packages/sirius-web/backend/sirius-web-application/pom.xml index 94fcff6538..576c419872 100644 --- a/packages/sirius-web/backend/sirius-web-application/pom.xml +++ b/packages/sirius-web/backend/sirius-web-application/pom.xml @@ -144,6 +144,16 @@ sirius-components-view-gantt-edit 2024.1.5 + + org.eclipse.sirius + sirius-components-domain + 2024.1.5 + + + org.eclipse.sirius + sirius-components-domain-edit + 2024.1.5 + org.eclipse.sirius sirius-components-domain-emf diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/CurrentTreeDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/CurrentTreeDescriptionProvider.java new file mode 100644 index 0000000000..1d4fb02730 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/CurrentTreeDescriptionProvider.java @@ -0,0 +1,247 @@ +/******************************************************************************* + * 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.relatedelements.services; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.MissingResourceException; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.edit.provider.IItemLabelProvider; +import org.eclipse.emf.edit.provider.ItemProviderAdapter; +import org.eclipse.sirius.components.core.CoreImageConstants; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.forms.TreeNode; +import org.eclipse.sirius.components.forms.WidgetIdProvider; +import org.eclipse.sirius.components.forms.components.TreeComponent; +import org.eclipse.sirius.components.forms.description.TreeDescription; +import org.eclipse.sirius.components.representations.Success; +import org.eclipse.sirius.components.representations.VariableManager; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.ICurrentTreeDescriptionProvider; +import org.springframework.stereotype.Service; + +/** + * Provides the definition of the tree widget for the "Current" panel in the "Related Elements" view. It displays two + * top-level categories, "Parent" and "Children", implemented as plain strings. + *
    + *
  • Inside "Parent" there is zero or one semantic element, the parent of the selected element (if it has one).
  • + *
  • Inside "Children" there is one sub-category per non-empty containment reference of the selected element. The + * categories are implemented using the corresponding EReference.
  • + *
  • Finally, inside a given reference sub-category there is one node per semantic element contained through that + * reference. + *
  • + *
+ * + * @author pcdavid + */ +@Service +public class CurrentTreeDescriptionProvider implements ICurrentTreeDescriptionProvider { + + private static final String WIDGET_ID = "related/current"; + + private static final String CATEGORY_PARENT = "Parent"; + + private static final String CATEGORY_CHILDREN = "Children"; + + private static final String TITLE = "Current"; + + private static final String WIDGET_ICON_URL = "/icons/svg/arrow_downward_black_24dp.svg"; + + private static final String FOLDER_ICON_URL = "/icons/svg/folder_black_24dp.svg"; + + private static final String CHILDREN_CATEGORY_ICON_URL = "/icons/svg/subdirectory_arrow_right_black_24dp.svg"; + + private static final String CATEGORY_KIND = "siriusWeb://category"; + + private static final String CONTAINMENT_REFERENCE_KIND = "siriusWeb://category/containment-reference"; + + private final IObjectService objectService; + + private final ComposedAdapterFactory adapterFactory; + + public CurrentTreeDescriptionProvider(IObjectService objectService, ComposedAdapterFactory adapterFactory) { + this.objectService = Objects.requireNonNull(objectService); + this.adapterFactory = Objects.requireNonNull(adapterFactory); + } + + @Override + public TreeDescription getTreeDescription() { + return TreeDescription.newTreeDescription(WIDGET_ID) + .idProvider(new WidgetIdProvider()) + .targetObjectIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null)) + .diagnosticsProvider(variableManager -> List.of()) + .kindProvider(variableManager -> "") + .messageProvider(variableManager -> "") + .labelProvider(variableManager -> TITLE) + .iconURLProvider(variableManager -> List.of(WIDGET_ICON_URL)) + .nodeIdProvider(this::getNodeId) + .nodeLabelProvider(this::getNodeLabel) + .nodeIconURLProvider(this::getNodeImageURL) + .nodeEndIconsURLProvider(variableManager -> List.of()) + .nodeKindProvider(this::getNodeKind) + .nodeSelectableProvider(this::isNodeSelectable) + .isCheckableProvider(variableManager -> false) + .checkedValueProvider(variableManager -> false) + .newCheckedValueHandler((variableManager, newValue) -> new Success()) + .childrenProvider(this::getCurrentChildren) + .expandedNodeIdsProvider(this::collectAllNodeIds) + .build(); + } + + private String getNodeId(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof String) { + result = "category/" + self; + } else if (self instanceof EReference eReference) { + result = "reference/" + eReference.getName(); + } else if (self != null) { + result = this.objectService.getId(self); + } + return result; + } + + private String getNodeLabel(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof String string) { + result = string; + } else if (self instanceof EReference eReference) { + var optionalRootEObject = variableManager.get(TreeComponent.ROOT_VARIABLE, EObject.class); + if (optionalRootEObject.isPresent()) { + result = this.getContainmentReferenceLabel(optionalRootEObject.get(), eReference); + } + if (result == null) { + result = this.objectService.getLabel(self); + } + } else if (self != null) { + result = this.objectService.getLabel(self); + } + return result; + } + + /** + * EMF Edit does not generate IItemPropertyDescriptors for containment references, so we have to resort to looking + * up the label directly in the ResourceLocator. + */ + private String getContainmentReferenceLabel(EObject eObject, EReference eReference) { + Adapter adapter = this.adapterFactory.adapt(eObject, IItemLabelProvider.class); + if (adapter instanceof ItemProviderAdapter editingDomainItemProvider) { + String key = String.format("_UI_%s_%s_feature", eReference.getEContainingClass().getName(), eReference.getName()); + try { + return editingDomainItemProvider.getString(key); + } catch (MissingResourceException mre) { + // Expected for dynamic instances. + } + } + return null; + } + + private List getNodeImageURL(VariableManager variableManager) { + List result = List.of(CoreImageConstants.DEFAULT_SVG); + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof String) { + result = List.of(FOLDER_ICON_URL); + } else if (self instanceof EReference) { + result = List.of(CHILDREN_CATEGORY_ICON_URL); + } else if (self != null) { + result = this.objectService.getImagePath(self); + } + return result; + } + + private String getNodeKind(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof String) { + result = CATEGORY_KIND; + } else if (self instanceof EReference) { + result = CONTAINMENT_REFERENCE_KIND; + } else if (self != null) { + result = this.objectService.getKind(self); + } + return result; + } + + private boolean isNodeSelectable(VariableManager variableManager) { + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + return self instanceof EObject && !(self instanceof EReference); + } + + private List getCurrentChildren(VariableManager variableManager) { + var self = variableManager.get(VariableManager.SELF, Object.class); + var root = variableManager.get(TreeComponent.ROOT_VARIABLE, EObject.class); + var ancestors = variableManager.get(TreeComponent.ANCESTORS_VARIABLE, List.class); + if (root.isPresent() && self.isPresent() && ancestors.isPresent()) { + return this.getCurrentChildren(self.get(), root.get(), ancestors.get()); + } else { + return List.of(); + } + } + + private List getCurrentChildren(Object self, EObject root, List ancestors) { + List result = List.of(); + if (ancestors.isEmpty()) { + result = List.of(CATEGORY_PARENT, CATEGORY_CHILDREN); + } else if (self.equals(CATEGORY_PARENT) && root.eContainer() != null) { + result = List.of(root.eContainer()); + } else if (self.equals(CATEGORY_CHILDREN)) { + result = this.getNonEmptyContainmentReferences(root); + } else if (self instanceof EReference) { + result = this.readReference(root, (EReference) self); + } + return result; + } + + private List getNonEmptyContainmentReferences(EObject self) { + return self.eClass().getEAllReferences().stream() + .filter(EReference::isContainment) + .filter(eReference -> { + if (eReference.isMany()) { + return !((EList) self.eGet(eReference)).isEmpty(); + } else { + return self.eGet(eReference) != null; + } + }) + .sorted(Comparator.comparing(EStructuralFeature::getName)) + .toList(); + } + + private List readReference(EObject self, EReference eReference) { + List result; + if (eReference.isMany()) { + result = (EList) self.eGet(eReference); + } else { + result = Optional.ofNullable(self.eGet(eReference)).stream().toList(); + } + return result; + } + + private List collectAllNodeIds(VariableManager variableManager) { + List result = new ArrayList<>(); + for (var element : variableManager.get(TreeComponent.NODES_VARIABLE, List.class).orElse(List.of())) { + if (element instanceof TreeNode node) { + result.add(node.getId()); + } + } + return result; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingReferences.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingReferences.java new file mode 100644 index 0000000000..5d346355e5 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingReferences.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.relatedelements.services; + +import java.util.List; +import java.util.Objects; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; + +/** + * Helper to represent the set of source objects which point to the current element through the same EReference. + * + * @author pcdavid + */ +public record IncomingReferences(EReference eReference, List sources) { + public IncomingReferences { + Objects.requireNonNull(eReference); + Objects.requireNonNull(sources); + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingTreeDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingTreeDescriptionProvider.java new file mode 100644 index 0000000000..2491d10896 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/IncomingTreeDescriptionProvider.java @@ -0,0 +1,207 @@ +/******************************************************************************* + * 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.relatedelements.services; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Objects; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.edit.provider.IItemLabelProvider; +import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; +import org.eclipse.emf.edit.provider.IItemPropertySource; +import org.eclipse.emf.edit.provider.ItemProviderAdapter; +import org.eclipse.sirius.components.core.CoreImageConstants; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.forms.TreeNode; +import org.eclipse.sirius.components.forms.WidgetIdProvider; +import org.eclipse.sirius.components.forms.components.TreeComponent; +import org.eclipse.sirius.components.forms.description.TreeDescription; +import org.eclipse.sirius.components.representations.Success; +import org.eclipse.sirius.components.representations.VariableManager; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.IIncomingTreeDescriptionProvider; +import org.springframework.stereotype.Service; + +/** + * Provides the definition of the tree widget for the "Incoming" panel in the "Related Elements" view. + * + * @author pcdavid + */ +@Service +public class IncomingTreeDescriptionProvider implements IIncomingTreeDescriptionProvider { + + private static final String WIDGET_ID = "related/incoming"; + + private static final String TITLE = "Incoming"; + + private static final String WIDGET_ICON_URL = "/images/west_black_24dp.svg"; + + private static final String INCOMING_REFERENCE_ICON_URL = "/images/west_black_24dp.svg"; + + private static final String INCOMING_REFERENCES_KIND = "siriusWeb://category/incoming-references"; + + private final IObjectService objectService; + + private final ComposedAdapterFactory adapterFactory; + + public IncomingTreeDescriptionProvider(IObjectService objectService, ComposedAdapterFactory adapterFactory) { + this.objectService = Objects.requireNonNull(objectService); + this.adapterFactory = Objects.requireNonNull(adapterFactory); + } + + @Override + public TreeDescription getTreeDescription() { + return TreeDescription.newTreeDescription(WIDGET_ID) + .idProvider(new WidgetIdProvider()) + .targetObjectIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null)) + .diagnosticsProvider(variableManager -> List.of()) + .kindProvider(variableManager -> "") + .messageProvider(variableManager -> "") + .labelProvider(variableManager -> TITLE) + .iconURLProvider(variableManager -> List.of(WIDGET_ICON_URL)) + .nodeIdProvider(this::getNodeId) + .nodeLabelProvider(this::getNodeLabel) + .nodeIconURLProvider(this::getNodeImageURL) + .nodeEndIconsURLProvider(variableManager -> List.of()) + .nodeKindProvider(this::getNodeKind) + .nodeSelectableProvider(this::isNodeSelectable) + .childrenProvider(this::getIncomingChildren) + .expandedNodeIdsProvider(this::collectAllNodeIds) + .isCheckableProvider(variableManager -> false) + .checkedValueProvider(variableManager -> false) + .newCheckedValueHandler((variableManager, newValue) -> new Success()) + .build(); + } + + private String getNodeId(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof IncomingReferences incomingReferences) { + result = "reference/" + incomingReferences.eReference().getName(); + } else if (self != null) { + result = this.objectService.getId(self); + } + return result; + } + + private String getNodeLabel(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof IncomingReferences incomingReferences) { + EReference eReference = incomingReferences.eReference(); + EObject eObject = incomingReferences.sources().get(0); + result = eReference.getName(); + if (eReference.isContainment()) { + result = "owned " + result; + Adapter adapter = this.adapterFactory.adapt(eObject, IItemLabelProvider.class); + if (adapter instanceof ItemProviderAdapter editingDomainItemProvider) { + String key = String.format("_UI_%s_%s_feature", eReference.getEContainingClass().getName(), eReference.getName()); + try { + result = editingDomainItemProvider.getString(key); + } catch (MissingResourceException mre) { + // Expected for dynamic instances. + } + } + } else { + Adapter adapter = this.adapterFactory.adapt(eObject, IItemPropertySource.class); + if (adapter instanceof IItemPropertySource itemPropertySource) { + IItemPropertyDescriptor descriptor = itemPropertySource.getPropertyDescriptor(eObject, eReference); + if (descriptor != null) { + result = descriptor.getDisplayName(eReference); + } else { + result = eReference.getName(); + } + } + } + } else if (self != null) { + result = this.objectService.getLabel(self); + } + return result; + } + + private List getNodeImageURL(VariableManager variableManager) { + List result = List.of(CoreImageConstants.DEFAULT_SVG); + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof IncomingReferences) { + result = List.of(INCOMING_REFERENCE_ICON_URL); + } else if (self != null) { + result = this.objectService.getImagePath(self); + } + return result; + } + + private String getNodeKind(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof IncomingReferences) { + result = INCOMING_REFERENCES_KIND; + } else if (self != null) { + result = this.objectService.getKind(self); + } + return result; + } + + private boolean isNodeSelectable(VariableManager variableManager) { + return variableManager.get(VariableManager.SELF, EObject.class).isPresent(); + } + + private List getIncomingChildren(VariableManager variableManager) { + var self = variableManager.get(VariableManager.SELF, Object.class); + var root = variableManager.get(TreeComponent.ROOT_VARIABLE, EObject.class); + var ancestors = variableManager.get(TreeComponent.ANCESTORS_VARIABLE, List.class); + if (root.isPresent() && self.isPresent() && ancestors.isPresent()) { + return this.getIncomingChildren(self.get(), root.get(), ancestors.get()); + } else { + return List.of(); + } + } + + private List getIncomingChildren(Object self, EObject root, List ancestors) { + List result = List.of(); + if (ancestors.isEmpty()) { + ECrossReferenceAdapter xref = ECrossReferenceAdapter.getCrossReferenceAdapter(root); + if (xref != null) { + var settings = xref.getInverseReferences(root).stream() + .sorted(Comparator.comparing(setting -> setting.getEStructuralFeature().getName())) + .toList(); + Map> sourceByReference = new LinkedHashMap<>(); + for (EStructuralFeature.Setting setting : settings) { + sourceByReference.computeIfAbsent((EReference) setting.getEStructuralFeature(), ref -> new ArrayList<>()).add(setting.getEObject()); + } + result = sourceByReference.entrySet().stream().map(entry -> new IncomingReferences(entry.getKey(), entry.getValue())).toList(); + } + } else if (self instanceof IncomingReferences incomingReferences) { + result = incomingReferences.sources(); + } + return result; + } + + private List collectAllNodeIds(VariableManager variableManager) { + List result = new ArrayList<>(); + for (var element : variableManager.get(TreeComponent.NODES_VARIABLE, List.class).orElse(List.of())) { + if (element instanceof TreeNode node) { + result.add(node.getId()); + } + } + return result; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/OutgoingTreeDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/OutgoingTreeDescriptionProvider.java new file mode 100644 index 0000000000..84096fdd11 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/OutgoingTreeDescriptionProvider.java @@ -0,0 +1,216 @@ +/******************************************************************************* + * 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.relatedelements.services; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.emf.common.notify.Adapter; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.edit.provider.ComposedAdapterFactory; +import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; +import org.eclipse.emf.edit.provider.IItemPropertySource; +import org.eclipse.sirius.components.core.CoreImageConstants; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.forms.TreeNode; +import org.eclipse.sirius.components.forms.WidgetIdProvider; +import org.eclipse.sirius.components.forms.components.TreeComponent; +import org.eclipse.sirius.components.forms.description.TreeDescription; +import org.eclipse.sirius.components.representations.Success; +import org.eclipse.sirius.components.representations.VariableManager; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.IOutgoingTreeDescriptionProvider; +import org.springframework.stereotype.Service; + +/** + * Provides the definition of the tree widget for the "Outgoing" panel in the "Related Elements" view. It has two + * levels: + *
    + *
  1. Level 1: one category node per non-containment reference of the selected element which references at least one + * element. The target element for these nodes is the EReference in question.
  2. + *
  3. Level 2: inside a given category (EReference), all the semantic model elements that the selected element points + * to through this particular reference.
  4. + *
+ * + * @author pcdavid + */ +@Service +public class OutgoingTreeDescriptionProvider implements IOutgoingTreeDescriptionProvider { + + private static final String WIDGET_ID = "related/outgoing"; + + private static final String TITLE = "Outgoing"; + + private static final String WIDGET_ICON_URL = "/icons/svg/east_black_24dp.svg"; + + private static final String OUTGOING_REFERENCE_ICON_URL = "/icons/svg/east_black_24dp.svg"; + + private static final String OUTGOING_REFERENCE_KIND = "siriusWeb://category/outgoing-references"; + + private final IObjectService objectService; + + private final ComposedAdapterFactory adapterFactory; + + public OutgoingTreeDescriptionProvider(IObjectService objectService, ComposedAdapterFactory adapterFactory) { + this.objectService = Objects.requireNonNull(objectService); + this.adapterFactory = Objects.requireNonNull(adapterFactory); + } + + @Override + public TreeDescription getTreeDescription() { + return TreeDescription.newTreeDescription(WIDGET_ID) + .idProvider(new WidgetIdProvider()) + .targetObjectIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null)) + .diagnosticsProvider(variableManager -> List.of()) + .kindProvider(variableManager -> "") + .messageProvider(variableManager -> "") + .labelProvider(variableManager -> TITLE) + .iconURLProvider(variableManager -> List.of(WIDGET_ICON_URL)) + .nodeIdProvider(this::getNodeId) + .nodeLabelProvider(this::getNodeLabel) + .nodeIconURLProvider(this::getNodeImageURL) + .nodeEndIconsURLProvider(variableManager -> List.of()) + .nodeKindProvider(this::getNodeKind) + .nodeSelectableProvider(this::isNodeSelectable) + .childrenProvider(this::getOutgoingChildren) + .expandedNodeIdsProvider(this::collectAllNodeIds) + .isCheckableProvider(variableManager -> false) + .checkedValueProvider(variableManager -> false) + .newCheckedValueHandler((variableManager, newValue) -> new Success()) + .build(); + } + + private String getNodeId(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof EReference eReference) { + result = "reference/" + eReference.getName(); + } else if (self != null) { + result = this.objectService.getId(self); + } + return result; + } + + private String getNodeLabel(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof EReference eReference) { + result = this.objectService.getLabel(eReference); + var optionalRootEObject = variableManager.get(VariableManager.SELF, EObject.class); + if (optionalRootEObject.isPresent()) { + result = this.getDisplayName(eReference, optionalRootEObject.get()); + } + } else if (self != null) { + result = this.objectService.getLabel(self); + } + return result; + } + + private String getDisplayName(EReference eReference, EObject eObject) { + String result = null; + Adapter adapter = this.adapterFactory.adapt(eObject, IItemPropertySource.class); + if (adapter instanceof IItemPropertySource itemPropertySource) { + IItemPropertyDescriptor descriptor = itemPropertySource.getPropertyDescriptor(eObject, eReference); + if (descriptor != null) { + result = descriptor.getDisplayName(eReference); + } else { + result = eReference.getName(); + } + } + return result; + } + + private List getNodeImageURL(VariableManager variableManager) { + List result = List.of(CoreImageConstants.DEFAULT_SVG); + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof EReference) { + result = List.of(OUTGOING_REFERENCE_ICON_URL); + } else if (self != null) { + result = this.objectService.getImagePath(self); + } + return result; + } + + private String getNodeKind(VariableManager variableManager) { + String result = null; + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + if (self instanceof EReference) { + result = OUTGOING_REFERENCE_KIND; + } else if (self != null) { + result = this.objectService.getKind(self); + } + return result; + } + + private boolean isNodeSelectable(VariableManager variableManager) { + var self = variableManager.get(VariableManager.SELF, Object.class).orElse(null); + return self instanceof EObject && !(self instanceof EReference); + } + + private List getOutgoingChildren(VariableManager variableManager) { + var self = variableManager.get(VariableManager.SELF, Object.class); + var root = variableManager.get(TreeComponent.ROOT_VARIABLE, EObject.class); + var ancestors = variableManager.get(TreeComponent.ANCESTORS_VARIABLE, List.class); + if (root.isPresent() && self.isPresent() && ancestors.isPresent()) { + return this.getOutgoingChildren(self.get(), root.get(), ancestors.get()); + } else { + return List.of(); + } + } + + private List getOutgoingChildren(Object self, EObject root, List ancestors) { + List result = List.of(); + if (ancestors.isEmpty()) { + var nonContainmentReferences = root.eClass().getEAllReferences().stream() + .filter(ref -> !ref.isContainment()) + .sorted(Comparator.comparing(EStructuralFeature::getName)) + .toList(); + + result = nonContainmentReferences.stream().filter(ref -> { + if (ref.isMany()) { + return !((EList) root.eGet(ref)).isEmpty(); + } else { + return root.eGet(ref) != null; + } + }).toList(); + } else if (self instanceof EReference eReference) { + result = this.readReference(root, eReference); + } + return result; + } + + private List readReference(EObject self, EReference ref) { + List result; + if (ref.isMany()) { + result = (EList) self.eGet(ref); + } else { + result = Optional.ofNullable(self.eGet(ref)).stream().toList(); + } + return result; + } + + private List collectAllNodeIds(VariableManager variableManager) { + List result = new ArrayList<>(); + for (var element : variableManager.get(TreeComponent.NODES_VARIABLE, List.class).orElse(List.of())) { + if (element instanceof TreeNode node) { + result.add(node.getId()); + } + } + return result; + } +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/RelatedElementsDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/RelatedElementsDescriptionProvider.java index b80829b610..ecde71c5f2 100644 --- a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/RelatedElementsDescriptionProvider.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/RelatedElementsDescriptionProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024, 2024 Obeo. + * 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 @@ -12,8 +12,24 @@ *******************************************************************************/ package org.eclipse.sirius.web.application.views.relatedelements.services; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Function; + import org.eclipse.sirius.components.collaborative.forms.api.IRelatedElementsDescriptionProvider; +import org.eclipse.sirius.components.core.api.IObjectService; +import org.eclipse.sirius.components.forms.GroupDisplayMode; +import org.eclipse.sirius.components.forms.description.AbstractControlDescription; import org.eclipse.sirius.components.forms.description.FormDescription; +import org.eclipse.sirius.components.forms.description.GroupDescription; +import org.eclipse.sirius.components.forms.description.PageDescription; +import org.eclipse.sirius.components.representations.GetOrCreateRandomIdProvider; +import org.eclipse.sirius.components.representations.VariableManager; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.ICurrentTreeDescriptionProvider; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.IIncomingTreeDescriptionProvider; +import org.eclipse.sirius.web.application.views.relatedelements.services.api.IOutgoingTreeDescriptionProvider; import org.springframework.stereotype.Service; /** @@ -23,8 +39,81 @@ */ @Service public class RelatedElementsDescriptionProvider implements IRelatedElementsDescriptionProvider { + + public static final String FORM_DESCRIPTION_ID = "relatedElements_form_description"; + + private static final String GROUP_DESCRIPTION_ID = "defaultRelatedElementsGroup"; + + private static final String PAGE_DESCRIPTION_ID = "defaultRelatedElementsPage"; + + private static final String FORM_TITLE = "Related Elements"; + + private final IObjectService objectService; + + private final IIncomingTreeDescriptionProvider incomingTreeDescriptionProvider; + + private final ICurrentTreeDescriptionProvider currentTreeDescriptionProvider; + + private final IOutgoingTreeDescriptionProvider outgoingTreeDescriptionProvider; + + public RelatedElementsDescriptionProvider(IObjectService objectService, IIncomingTreeDescriptionProvider incomingTreeDescriptionProvider, ICurrentTreeDescriptionProvider currentTreeDescriptionProvider, IOutgoingTreeDescriptionProvider outgoingTreeDescriptionProvider) { + this.objectService = Objects.requireNonNull(objectService); + this.incomingTreeDescriptionProvider = Objects.requireNonNull(incomingTreeDescriptionProvider); + this.currentTreeDescriptionProvider = Objects.requireNonNull(currentTreeDescriptionProvider); + this.outgoingTreeDescriptionProvider = Objects.requireNonNull(outgoingTreeDescriptionProvider); + } + @Override public FormDescription getFormDescription() { - return null; + List groupDescriptions = List.of(this.getGroupDescription()); + + Function targetObjectIdProvider = variableManager -> variableManager.get(VariableManager.SELF, Object.class) + .map(this.objectService::getId) + .orElse(null); + + return FormDescription.newFormDescription(FORM_DESCRIPTION_ID) + .label(FORM_TITLE) + .idProvider(new GetOrCreateRandomIdProvider()) + .targetObjectIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null)) + .labelProvider(variableManager -> FORM_TITLE) + .targetObjectIdProvider(targetObjectIdProvider) + .canCreatePredicate(variableManager -> false) + .pageDescriptions(List.of(this.getPageDescription(groupDescriptions))) + .build(); + } + + private GroupDescription getGroupDescription() { + List controlDescriptions = new ArrayList<>(); + controlDescriptions.add(this.incomingTreeDescriptionProvider.getTreeDescription()); + controlDescriptions.add(this.currentTreeDescriptionProvider.getTreeDescription()); + controlDescriptions.add(this.outgoingTreeDescriptionProvider.getTreeDescription()); + + return GroupDescription.newGroupDescription(GROUP_DESCRIPTION_ID) + .idProvider(variableManager -> FORM_TITLE) + .labelProvider(variableManager -> FORM_TITLE) + .displayModeProvider(variableManager -> GroupDisplayMode.TOGGLEABLE_AREAS) + .semanticElementsProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).stream().toList()) + .controlDescriptions(controlDescriptions) + .build(); + } + + private PageDescription getPageDescription(List groupDescriptions) { + Function idProvider = variableManager -> variableManager.get(VariableManager.SELF, Object.class) + .map(this.objectService::getId) + .orElseGet(() -> UUID.randomUUID().toString()); + + Function labelProvider = variableManager -> variableManager.get(VariableManager.SELF, Object.class) + .map(this.objectService::getLabel) + .orElse(""); + + Function> semanticElementsProvider = variableManager -> variableManager.get(VariableManager.SELF, Object.class).stream().toList(); + + return PageDescription.newPageDescription(PAGE_DESCRIPTION_ID) + .idProvider(idProvider) + .labelProvider(labelProvider) + .semanticElementsProvider(semanticElementsProvider) + .groupDescriptions(groupDescriptions) + .canCreatePredicate(variableManager -> true) + .build(); } } diff --git a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/IdPolicy.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/ICurrentTreeDescriptionProvider.java similarity index 57% rename from packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/IdPolicy.java rename to packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/ICurrentTreeDescriptionProvider.java index ea173b760f..74ac8024b2 100644 --- a/packages/forms/backend/sirius-components-forms-tests/src/main/java/org/eclipse/sirius/components/forms/tests/IdPolicy.java +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/ICurrentTreeDescriptionProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019, 2020 Obeo. + * 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 @@ -10,14 +10,15 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ -package org.eclipse.sirius.components.forms.tests; +package org.eclipse.sirius.web.application.views.relatedelements.services.api; + +import org.eclipse.sirius.components.forms.description.TreeDescription; /** - * Enumeration used to indicate if the identifiers should be taken into account while determining if form elements match - * one another. + * Provides the description of the tree widget for the current panel. * - * @author lfasani + * @author sbegaudeau */ -public enum IdPolicy { - WITH_ID, WITHOUT_ID +public interface ICurrentTreeDescriptionProvider { + TreeDescription getTreeDescription(); } diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IIncomingTreeDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IIncomingTreeDescriptionProvider.java new file mode 100644 index 0000000000..9e40080f87 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IIncomingTreeDescriptionProvider.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.relatedelements.services.api; + +import org.eclipse.sirius.components.forms.description.TreeDescription; + +/** + * Provides the description of the tree widget for the incoming panel. + * + * @author sbegaudeau + */ +public interface IIncomingTreeDescriptionProvider { + TreeDescription getTreeDescription(); +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IOutgoingTreeDescriptionProvider.java b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IOutgoingTreeDescriptionProvider.java new file mode 100644 index 0000000000..013eb53090 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/java/org/eclipse/sirius/web/application/views/relatedelements/services/api/IOutgoingTreeDescriptionProvider.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.relatedelements.services.api; + +import org.eclipse.sirius.components.forms.description.TreeDescription; + +/** + * Provides the description of the tree widget for the outgoing panel. + * + * @author sbegaudeau + */ +public interface IOutgoingTreeDescriptionProvider { + TreeDescription getTreeDescription(); +} diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/arrow_downward_black_24dp.svg b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/arrow_downward_black_24dp.svg new file mode 100644 index 0000000000..d320c1e976 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/arrow_downward_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/east_black_24dp.svg b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/east_black_24dp.svg new file mode 100644 index 0000000000..e3e703e072 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/east_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/folder_black_24dp.svg b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/folder_black_24dp.svg new file mode 100644 index 0000000000..c8da56daa5 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/folder_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/subdirectory_arrow_right_black_24dp.svg b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/subdirectory_arrow_right_black_24dp.svg new file mode 100644 index 0000000000..d74f1c8fe2 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/subdirectory_arrow_right_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/west_black_24dp.svg b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/west_black_24dp.svg new file mode 100644 index 0000000000..b7f7641210 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-application/src/main/resources/icons/svg/west_black_24dp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/emf/EMFAdapterFactoryConfiguration.java b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/emf/EMFAdapterFactoryConfiguration.java new file mode 100644 index 0000000000..a628aac178 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web-infrastructure/src/main/java/org/eclipse/sirius/web/infrastructure/emf/EMFAdapterFactoryConfiguration.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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.infrastructure.emf; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.sirius.components.domain.provider.DomainItemProviderAdapterFactory; +import org.eclipse.sirius.components.view.deck.util.DeckAdapterFactory; +import org.eclipse.sirius.components.view.diagram.provider.DiagramItemProviderAdapterFactory; +import org.eclipse.sirius.components.view.form.provider.FormItemProviderAdapterFactory; +import org.eclipse.sirius.components.view.gantt.provider.GanttItemProviderAdapterFactory; +import org.eclipse.sirius.components.view.provider.ViewItemProviderAdapterFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Configuration of EMF specific concepts. + * + * @author sbegaudeau + */ +@Configuration +public class EMFAdapterFactoryConfiguration { + + @Bean + public AdapterFactory domainAdapterFactory() { + return new DomainItemProviderAdapterFactory(); + } + + @Bean + public AdapterFactory viewAdapterFactory() { + return new ViewItemProviderAdapterFactory(); + } + + @Bean + public AdapterFactory diagramAdapterFactory() { + return new DiagramItemProviderAdapterFactory(); + } + + @Bean + public AdapterFactory formAdapterFactory() { + return new FormItemProviderAdapterFactory(); + } + + @Bean + public AdapterFactory deckAdapterFactory() { + return new DeckAdapterFactory(); + } + + @Bean + public AdapterFactory ganttAdapterFactory() { + return new GanttItemProviderAdapterFactory(); + } +} diff --git a/packages/sirius-web/backend/sirius-web-sample-application/pom.xml b/packages/sirius-web/backend/sirius-web-sample-application/pom.xml index 46d040722d..9289ba5500 100644 --- a/packages/sirius-web/backend/sirius-web-sample-application/pom.xml +++ b/packages/sirius-web/backend/sirius-web-sample-application/pom.xml @@ -219,12 +219,6 @@ sirius-components-view-emf-widget-reference 2024.1.5
- - org.eclipse.sirius - sirius-components-forms-tests - 2024.1.5 - test - org.springframework.boot spring-boot-starter-test diff --git a/packages/sirius-web/backend/sirius-web-sample-application/src/test/java/org/eclipse/sirius/web/sample/tests/ViewDetailsRenderingIntegrationTests.java b/packages/sirius-web/backend/sirius-web-sample-application/src/test/java/org/eclipse/sirius/web/sample/tests/ViewDetailsRenderingIntegrationTests.java index 366fc95000..dba375b97d 100644 --- a/packages/sirius-web/backend/sirius-web-sample-application/src/test/java/org/eclipse/sirius/web/sample/tests/ViewDetailsRenderingIntegrationTests.java +++ b/packages/sirius-web/backend/sirius-web-sample-application/src/test/java/org/eclipse/sirius/web/sample/tests/ViewDetailsRenderingIntegrationTests.java @@ -14,7 +14,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import static org.eclipse.sirius.components.forms.tests.FormAssertions.assertThat; import fr.obeo.dsl.designer.sample.flow.FlowPackage; diff --git a/packages/sirius-web/backend/sirius-web/pom.xml b/packages/sirius-web/backend/sirius-web/pom.xml index 2c1add4e2a..983d693ee3 100644 --- a/packages/sirius-web/backend/sirius-web/pom.xml +++ b/packages/sirius-web/backend/sirius-web/pom.xml @@ -69,6 +69,12 @@ junit-jupiter test + + org.eclipse.sirius + sirius-components-forms-tests + 2024.1.5 + test + diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/TestIdentifiers.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/TestIdentifiers.java index c8fe7c20bf..e591f12466 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/TestIdentifiers.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/TestIdentifiers.java @@ -31,5 +31,6 @@ public interface TestIdentifiers { UUID EPACKAGE_OBJECT = UUID.fromString("3237b215-ae23-48d7-861e-f542a4b9a4b8"); UUID EPACKAGE_PORTAL_REPRESENTATION = UUID.fromString("e81eec5c-42d6-491c-8bcc-9beb951356f8"); UUID DOMAIN_OBJECT = UUID.fromString("f8204cb6-3705-48a5-bee3-ad7e7d6cbdaf"); + UUID HUMAN_ENTITY_OBJECT = UUID.fromString("1731ffb5-bfb0-46f3-a23d-0c0650300005"); UUID PORTAL_REPRESENTATION_DESCRIPTION = UUID.fromString("69030a1b-0b5f-3c1d-8399-8ca260e4a672"); } diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/FormControllerIntegrationTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/FormControllerIntegrationTests.java index 0fe19598d7..82958b8c32 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/FormControllerIntegrationTests.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/FormControllerIntegrationTests.java @@ -13,6 +13,7 @@ package org.eclipse.sirius.web.application.controllers; import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.forms.tests.assertions.FormAssertions.assertThat; import com.jayway.jsonpath.JsonPath; @@ -34,8 +35,8 @@ import org.eclipse.sirius.components.core.api.SuccessPayload; import org.eclipse.sirius.components.forms.RichText; import org.eclipse.sirius.components.forms.Select; -import org.eclipse.sirius.components.forms.TreeNode; import org.eclipse.sirius.components.forms.TreeWidget; +import org.eclipse.sirius.components.forms.tests.navigation.FormNavigator; import org.eclipse.sirius.web.AbstractIntegrationTests; import org.eclipse.sirius.web.TestIdentifiers; import org.eclipse.sirius.web.services.FormVariableViewPreEditingContextProcessor; @@ -60,6 +61,7 @@ * @author sbegaudeau */ @Transactional +@SuppressWarnings("checkstyle:MultipleStringLiterals") @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class FormControllerIntegrationTests extends AbstractIntegrationTests { @@ -173,21 +175,14 @@ public void givenMasterDetailsBasedFormRepresentationWhenWeEditTheMasterPartThen .map(FormRefreshedEventPayload.class::cast) .map(FormRefreshedEventPayload::form) .filter(form -> { - var widgets = form.getPages().get(0).getGroups().get(0).getWidgets(); + var groupNavigator = new FormNavigator(form).page("Page").group("Group"); + var richText = groupNavigator.findWidget("RichText", RichText.class); + assertThat(richText).hasValue("first"); - widgets.stream() - .filter(Select.class::isInstance) - .map(Select.class::cast) - .findFirst() - .ifPresent(select -> selectId.set(select.getId())); + var select = groupNavigator.findWidget("Select", Select.class); + selectId.set(select.getId()); - var richText = widgets.stream() - .filter(RichText.class::isInstance) - .map(RichText.class::cast) - .findFirst() - .orElse(null); - - return richText.getValue().equals("first"); + return true; }) .isPresent(); @@ -211,14 +206,11 @@ public void givenMasterDetailsBasedFormRepresentationWhenWeEditTheMasterPartThen .map(FormRefreshedEventPayload.class::cast) .map(FormRefreshedEventPayload::form) .filter(form -> { - var widgets = form.getPages().get(0).getGroups().get(0).getWidgets(); - var richText = widgets.stream() - .filter(RichText.class::isInstance) - .map(RichText.class::cast) - .findFirst() - .orElse(null); - - return richText.getValue().equals("second"); + var groupNavigator = new FormNavigator(form).page("Page").group("Group"); + var richText = groupNavigator.findWidget("RichText", RichText.class); + assertThat(richText).hasValue("second"); + + return true; }) .isPresent(); @@ -267,22 +259,13 @@ public void givenViewBasedFormDescriptionWhenFormVariablesAreInitializedThenWidg .map(FormRefreshedEventPayload.class::cast) .map(FormRefreshedEventPayload::form) .filter(form -> { - var widgets = form.getPages().get(0).getGroups().get(0).getWidgets(); - - var checkedTreeNodes = widgets.stream() - .filter(TreeWidget.class::isInstance) - .map(TreeWidget.class::cast) - .flatMap(treeWidget -> treeWidget.getNodes().stream()) - .filter(TreeNode::isValue) - .toList(); - - var list = widgets.stream() - .filter(org.eclipse.sirius.components.forms.List.class::isInstance) - .map(org.eclipse.sirius.components.forms.List.class::cast) - .findFirst() - .orElse(null); - - return list.getItems().size() == 1 && checkedTreeNodes.stream().allMatch(node -> node.getLabel().equals("Root")); + var groupNavigator = new FormNavigator(form).page("Page").group("Group"); + var listWidget = groupNavigator.findWidget("List", org.eclipse.sirius.components.forms.List.class); + assertThat(listWidget.getItems()).hasSize(1); + + var treeWidget = groupNavigator.findWidget("Tree", TreeWidget.class); + assertThat(treeWidget).hasCheckedTreeItemsSize(1); + return true; }) .isPresent(); diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/RelatedElementsViewControllerIntegrationTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/RelatedElementsViewControllerIntegrationTests.java new file mode 100644 index 0000000000..2e9c454ca7 --- /dev/null +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/controllers/RelatedElementsViewControllerIntegrationTests.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * 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.controllers; + +import static org.eclipse.sirius.components.forms.tests.assertions.FormAssertions.assertThat; + +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Predicate; + +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventProcessor; +import org.eclipse.sirius.components.collaborative.api.IEditingContextEventProcessorRegistry; +import org.eclipse.sirius.components.collaborative.forms.dto.FormRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.forms.dto.PropertiesEventInput; +import org.eclipse.sirius.components.forms.Form; +import org.eclipse.sirius.components.forms.GroupDisplayMode; +import org.eclipse.sirius.components.forms.TreeWidget; +import org.eclipse.sirius.components.forms.tests.navigation.FormNavigator; +import org.eclipse.sirius.web.AbstractIntegrationTests; +import org.eclipse.sirius.web.TestIdentifiers; +import org.eclipse.sirius.web.services.api.IGraphQLRequestor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import graphql.execution.DataFetcherResult; +import reactor.test.StepVerifier; + +/** + * Integration tests of the related elements view. + * + * @author sbegaudeau + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class RelatedElementsViewControllerIntegrationTests extends AbstractIntegrationTests { + + private static final String GET_RELATED_ELEMENTS_EVENT_SUBSCRIPTION = """ + subscription relatedElementsEvent($input: PropertiesEventInput!) { + relatedElementsEvent(input: $input) { + __typename + } + } + """; + + @Autowired + private IGraphQLRequestor graphQLRequestor; + + @Autowired + private IEditingContextEventProcessorRegistry editingContextEventProcessorRegistry; + + @BeforeEach + public void beforeEach() { + this.editingContextEventProcessorRegistry.getEditingContextEventProcessors().stream() + .map(IEditingContextEventProcessor::getEditingContextId) + .forEach(this.editingContextEventProcessorRegistry::disposeEditingContextEventProcessor); + } + + @Test + @DisplayName("Given a semantic object, when we subscribe to its related elements events, then the form is sent") + @Sql(scripts = {"/scripts/initialize.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void givenSemanticObjectWhenWeSubscribeToItsPropertiesEventsThenTheFormIsSent() { + var input = new PropertiesEventInput(UUID.randomUUID(), TestIdentifiers.SAMPLE_STUDIO_PROJECT.toString(), List.of(TestIdentifiers.HUMAN_ENTITY_OBJECT.toString())); + var flux = this.graphQLRequestor.subscribe(GET_RELATED_ELEMENTS_EVENT_SUBSCRIPTION, input); + + Predicate
formPredicate = form -> { + var groupNavigator = new FormNavigator(form).page("Human").group("Related Elements"); + assertThat(groupNavigator.getGroup()).hasDisplayMode(GroupDisplayMode.TOGGLEABLE_AREAS); + + var incomingTreeWidget = groupNavigator.findWidget("Incoming", TreeWidget.class); + assertThat(incomingTreeWidget) + .hasTreeItemWithLabel("humans") + .hasTreeItemWithLabel("buck"); + + var currentTreeWidget = groupNavigator.findWidget("Current", TreeWidget.class); + assertThat(currentTreeWidget) + .hasTreeItemWithLabel("description") + .hasTreeItemWithLabel("promoted"); + + var outgoingTreeWidget = groupNavigator.findWidget("Outgoing", TreeWidget.class); + assertThat(outgoingTreeWidget) + .hasTreeItemWithLabel("NamedElement"); + + return true; + }; + + Predicate formContentMatcher = object -> Optional.of(object) + .filter(DataFetcherResult.class::isInstance) + .map(DataFetcherResult.class::cast) + .map(DataFetcherResult::getData) + .filter(FormRefreshedEventPayload.class::isInstance) + .map(FormRefreshedEventPayload.class::cast) + .map(FormRefreshedEventPayload::form) + .filter(formPredicate) + .isPresent(); + + StepVerifier.create(flux) + .expectNextMatches(formContentMatcher) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } +} diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/services/StudioLifecycleIntegrationTests.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/services/StudioLifecycleIntegrationTests.java index 6f6f9391cd..2eb817e36a 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/services/StudioLifecycleIntegrationTests.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/application/services/StudioLifecycleIntegrationTests.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.fail; import org.eclipse.sirius.components.core.api.IEditingContextSearchService; +import org.eclipse.sirius.components.domain.Domain; import org.eclipse.sirius.components.view.form.FormDescription; import org.eclipse.sirius.components.view.util.services.ColorPaletteService; import org.eclipse.sirius.web.AbstractIntegrationTests; @@ -102,4 +103,45 @@ public void givenStudioWhenItIsLoadedThenThenPaletteIsAvailable() { fail("Invalid editing context"); } } + + @Test + @DisplayName("Given a studio, when it is loaded, then its content can be manipulated") + @Sql(scripts = {"/scripts/initialize.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + @Sql(scripts = {"/scripts/cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void givenStudioWhenItIsLoadedThenItsContentCanBeManipulated() { + var optionalEditingContext = this.editingContextSearchService.findById(TestIdentifiers.SAMPLE_STUDIO_PROJECT.toString()); + assertThat(optionalEditingContext).isPresent(); + + var editingContext = optionalEditingContext.get(); + if (editingContext instanceof EditingContext siriusWebEditingContext) { + var resourceSet = siriusWebEditingContext.getDomain().getResourceSet(); + + var domain = resourceSet.getResources().stream() + .filter(resource -> !resource.getContents().isEmpty()) + .map(resource -> resource.getContents().get(0)) + .filter(Domain.class::isInstance) + .map(Domain.class::cast) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Missing domain")); + + assertThat(domain.getName()).isEqualTo("buck"); + + var domainString = domain.toString(); + assertThat(domainString.substring(domainString.indexOf("("))).isEqualTo("(name: buck)"); + + this.assertEntityContent(domain, "Root", "(name: Root) (abstract: false)"); + this.assertEntityContent(domain, "NamedElement", "(name: NamedElement) (abstract: true)"); + this.assertEntityContent(domain, "Human", "(name: Human) (abstract: false)"); + } + } + + private void assertEntityContent(Domain domain, String name, String content) { + var root = domain.getTypes().stream() + .filter(entity -> entity.getName().equals(name)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Missing entity")); + + var rootString = root.toString(); + assertThat(rootString.substring(rootString.indexOf("("))).isEqualTo(content); + } } diff --git a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/FormVariableViewPreEditingContextProcessor.java b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/FormVariableViewPreEditingContextProcessor.java index 13c0ea2345..e32b055a83 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/FormVariableViewPreEditingContextProcessor.java +++ b/packages/sirius-web/backend/sirius-web/src/test/java/org/eclipse/sirius/web/services/FormVariableViewPreEditingContextProcessor.java @@ -79,7 +79,7 @@ private FormDescription createFormDescription() { TreeDescription treeDescription = new TreeDescriptionBuilder() .name("Tree") .childrenExpression("aql:self.eContents()}") - .labelExpression("aql:self") + .labelExpression("Tree") .treeItemLabelExpression("aql:self.name") .isCheckableExpression("aql:true") .checkedValueExpression("aql:listValues->includes(self)") @@ -87,17 +87,20 @@ private FormDescription createFormDescription() { ListDescription listDescription = new ListDescriptionBuilder() .name("List") + .labelExpression("List") .displayExpression("aql:candidate.name") .valueExpression("aql:listValues") .build(); GroupDescription groupDescription = new GroupDescriptionBuilder() .name(NAME) + .labelExpression("Group") .children(treeDescription, listDescription) .build(); PageDescription pageDescription = new PageDescriptionBuilder() .name(NAME) + .labelExpression("Page") .domainType("domain:Domain") .groups(groupDescription) .build(); diff --git a/packages/sirius-web/backend/sirius-web/src/test/resources/scripts/initialize.sql b/packages/sirius-web/backend/sirius-web/src/test/resources/scripts/initialize.sql index 50429113f7..11207e773c 100644 --- a/packages/sirius-web/backend/sirius-web/src/test/resources/scripts/initialize.sql +++ b/packages/sirius-web/backend/sirius-web/src/test/resources/scripts/initialize.sql @@ -91,7 +91,7 @@ INSERT INTO document ( 'f0e490c1-79f1-49a0-b1f2-3637f2958148', 'e344d967-a639-4f6c-9c00-a466d51063c6', 'Domain', - '{"json":{"version":"1.0","encoding":"utf-8"},"ns":{"domain":"http://www.eclipse.org/sirius-web/domain"},"content":[{"id":"f8204cb6-3705-48a5-bee3-ad7e7d6cbdaf","eClass":"domain:Domain","data":{"name":"buck","types":[{"id":"c341bf91-d315-4264-9787-c51b121a6375","eClass":"domain:Entity","data":{"name":"Root","attributes":[{"id":"7ac92c9d-3cb6-4374-9774-11bb62962fe2","eClass":"domain:Attribute","data":{"name":"label"}}],"relations":[{"id":"f8fefc5d-4fee-4666-815e-94b24a95183f","eClass":"domain:Relation","data":{"name":"humans","many":true,"containment":true,"targetType":"//@types.1"}}]}},{"id":"1731ffb5-bfb0-46f3-a23d-0c0650300005","eClass":"domain:Entity","data":{"name":"Human","attributes":[{"id":"e34109d2-f51b-4070-af0e-da8b31c1f830","eClass":"domain:Attribute","data":{"name":"name"}},{"id":"e86d3f45-d043-441e-b8ab-12e4b3f8915a","eClass":"domain:Attribute","data":{"name":"description"}},{"id":"703e6db4-a193-4da7-a872-6efba2b3a2c5","eClass":"domain:Attribute","data":{"name":"promoted","type":"BOOLEAN"}}]}}]}}]}', + '{"json":{"version":"1.0","encoding":"utf-8"},"ns":{"domain":"http://www.eclipse.org/sirius-web/domain"},"content":[{"id":"f8204cb6-3705-48a5-bee3-ad7e7d6cbdaf","eClass":"domain:Domain","data":{"name":"buck","types":[{"id":"c341bf91-d315-4264-9787-c51b121a6375","eClass":"domain:Entity","data":{"name":"Root","attributes":[{"id":"7ac92c9d-3cb6-4374-9774-11bb62962fe2","eClass":"domain:Attribute","data":{"name":"label"}}],"relations":[{"id":"f8fefc5d-4fee-4666-815e-94b24a95183f","eClass":"domain:Relation","data":{"name":"humans","many":true,"containment":true,"targetType":"//@types.2"}}]}},{"id":"c6fdba07-dea5-4a53-99c7-7eefc1bfdfcc","eClass":"domain:Entity","data":{"name":"NamedElement","attributes":[{"id":"520bb7c9-5f28-40f7-bda0-b35dd593876d","eClass":"domain:Attribute","data":{"name":"name"}}],"abstract":true}},{"id":"1731ffb5-bfb0-46f3-a23d-0c0650300005","eClass":"domain:Entity","data":{"name":"Human","attributes":[{"id":"e86d3f45-d043-441e-b8ab-12e4b3f8915a","eClass":"domain:Attribute","data":{"name":"description"}},{"id":"703e6db4-a193-4da7-a872-6efba2b3a2c5","eClass":"domain:Attribute","data":{"name":"promoted","type":"BOOLEAN"}}],"superTypes":["//@types.1"]}}]}}]}', '2024-01-01 9:42:0.000', '2024-01-02 9:42:0.000' ); diff --git a/scripts/check-coverage.jsh b/scripts/check-coverage.jsh index fc46046c74..a880cfa130 100644 --- a/scripts/check-coverage.jsh +++ b/scripts/check-coverage.jsh @@ -48,8 +48,8 @@ var moduleCoverageData = List.of( new ModuleCoverage("sirius-components-collaborative-deck", 15.0), new ModuleCoverage("sirius-components-deck-graphql", 36.0), new ModuleCoverage("sirius-components-forms", 81.0), - new ModuleCoverage("sirius-components-collaborative-forms", 82.0), - new ModuleCoverage("sirius-components-forms-graphql", 53.0), + new ModuleCoverage("sirius-components-collaborative-forms", 85.0), + new ModuleCoverage("sirius-components-forms-graphql", 57.0), new ModuleCoverage("sirius-components-widget-reference", 70.0), new ModuleCoverage("sirius-components-collaborative-widget-reference", 54.0), new ModuleCoverage("sirius-components-widget-reference-graphql", 28.0), @@ -75,8 +75,8 @@ var moduleCoverageData = List.of( new ModuleCoverage("sirius-components-graphql", 54.0), new ModuleCoverage("sirius-components-web", 54.0), new ModuleCoverage("sirius-components-starter", 72.0), - new ModuleCoverage("sirius-components-domain", 69.0), - new ModuleCoverage("sirius-components-domain-edit", 22.0), + new ModuleCoverage("sirius-components-domain", 72.0), + new ModuleCoverage("sirius-components-domain-edit", 49.0), new ModuleCoverage("sirius-components-domain-design", 29.0), new ModuleCoverage("sirius-components-domain-emf", 98.0), new ModuleCoverage("sirius-components-view", 57.0), @@ -88,7 +88,7 @@ var moduleCoverageData = List.of( new ModuleCoverage("sirius-components-widget-reference-view", 28.0), new ModuleCoverage("sirius-components-widget-reference-view-edit", 3.0), new ModuleCoverage("sirius-components-view-gantt", 40.0), - new ModuleCoverage("sirius-components-view-gantt-edit", 6.0), + new ModuleCoverage("sirius-components-view-gantt-edit", 7.0), new ModuleCoverage("sirius-components-view-deck", 34.0), new ModuleCoverage("sirius-components-view-deck-edit", 4.0), new ModuleCoverage("sirius-components-view-emf", 58.0), @@ -103,7 +103,7 @@ var moduleCoverageData = List.of( new ModuleCoverage("sirius-web-customnodes-edit", 5.0), new ModuleCoverage("sirius-web-domain", 80.0), new ModuleCoverage("sirius-web-application", 92.0), - new ModuleCoverage("sirius-web-infrastructure", 85.0), + new ModuleCoverage("sirius-web-infrastructure", 86.0), new ModuleCoverage("sirius-web-starter", 98.0), new ModuleCoverage("sirius-web", 37.0) ); @@ -135,7 +135,7 @@ System.out.println(); // Check global code coverage double global = checkCoverage(""); -double expectedGlobalCoverage = 50.0; +double expectedGlobalCoverage = 51.0; boolean isValidCoverage = global >= expectedGlobalCoverage; display("total", global, expectedGlobalCoverage);