diff --git a/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF index ade9b1f75bf..b2f614a319b 100644 --- a/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name -Bundle-SymbolicName: org.eclipse.e4.emf.xpath +Bundle-SymbolicName: org.eclipse.e4.emf.xpath;deprecated:="This bundle is deprecated since 2025-03 (removal in 2027-03 or later)" Bundle-Version: 0.6.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-17 Require-Bundle: org.eclipse.emf.ecore;bundle-version="2.35.0", diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java index 47f9689e0de..64bca787569 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/EcoreXPathContextFactory.java @@ -21,6 +21,7 @@ * * @since 1.0 */ +@Deprecated(forRemoval = true, since = "2025-03 (removal in 2027-03 or later)") public class EcoreXPathContextFactory { /** diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java index fe24ab48698..a596b220cf1 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2024 BestSolution.at and others. + * Copyright (c) 2010, 2025 BestSolution.at and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -23,7 +23,11 @@ * Context in which the xpath is executed * * @since 1.0 + * @deprecated To query an E4-model use + * {@code org.eclipse.e4.ui.workbench.modeling.EModelService#findMatchingElements(org.eclipse.e4.ui.model.application.MApplicationElement, String, Class)} + * instead. */ +@Deprecated(forRemoval = true, since = "2025-03 (removal in 2027-03 or later)") public interface XPathContext { /** diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java index 3e5b503229a..d3e301ff452 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathContextFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2024 BestSolution.at and others. + * Copyright (c) 2010, 2025 BestSolution.at and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -19,7 +19,11 @@ * Factory responsible to create an XPath-Context * * @param the object type the XPath is created for + * @deprecated To query an E4-model use + * {@code org.eclipse.e4.ui.workbench.modeling.EModelService#findMatchingElements(org.eclipse.e4.ui.model.application.MApplicationElement, String, Class)} + * instead. */ +@Deprecated(forRemoval = true, since = "2025-03 (removal in 2027-03 or later)") public abstract class XPathContextFactory { /** @@ -38,10 +42,15 @@ public abstract class XPathContextFactory { * @param parentContext parent context * @param contextBean Object * @return XPathContext + * @deprecated The parent-context does not provide any real value. Just use + * {@link #newContext(Object)} */ public abstract XPathContext newContext(XPathContext parentContext, T contextBean); /** + * Creates a new {@code XPathContextFactory} that's suitable to query + * the E4-model. + * * @param the object type the xpath is created for * @return Create a new XPath-Factory */ diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java index 34c8b0d0845..39543fa8e5a 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/XPathNotFoundException.java @@ -20,6 +20,7 @@ * * @since 0.6 */ +@Deprecated(forRemoval = true, since = "2025-03 (removal in 2027-03 or later)") public class XPathNotFoundException extends IllegalArgumentException { private static final long serialVersionUID = -4174244860692153739L; diff --git a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java index 4dc93d5c421..ae83f16bed9 100644 --- a/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java +++ b/bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/JavaXPathContextFactoryImpl.java @@ -57,6 +57,7 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; +@SuppressWarnings({ "deprecation", "removal" }) public class JavaXPathContextFactoryImpl extends XPathContextFactory { private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance(); diff --git a/bundles/org.eclipse.e4.ui.model.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.model.workbench/META-INF/MANIFEST.MF index 5bae0a2e538..5a27e839f92 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.ui.model.workbench/META-INF/MANIFEST.MF @@ -2,11 +2,15 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.e4.ui.model.workbench;singleton:=true -Bundle-Version: 2.4.400.qualifier +Bundle-Version: 2.4.500.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: JavaSE-17 -Export-Package: org.eclipse.e4.ui.model;x-friends:="org.eclipse.e4.ui.workbench,org.eclipse.e4.ui.workbench.swt,org.eclipse.ui.workbench", +Export-Package: org.eclipse.e4.ui.model; + x-friends:="org.eclipse.e4.ui.workbench, + org.eclipse.e4.ui.workbench.swt, + org.eclipse.ui.workbench, + org.eclipse.e4.tools.emf.ui", org.eclipse.e4.ui.model.application, org.eclipse.e4.ui.model.application.commands, org.eclipse.e4.ui.model.application.commands.impl; diff --git a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/ModelXPathEvaluator.java b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/ModelXPathEvaluator.java new file mode 100644 index 00000000000..ac3a1408512 --- /dev/null +++ b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/ModelXPathEvaluator.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2025 Hannes Wellmann and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Hannes Wellmann - initial API and implementation + *******************************************************************************/ +package org.eclipse.e4.ui.model; + +import java.util.stream.Stream; +import org.eclipse.e4.emf.xpath.XPathContextFactory; +import org.eclipse.e4.ui.model.application.MApplicationElement; + +public class ModelXPathEvaluator { + + @SuppressWarnings({ "deprecation", "removal" }) + public static Stream findMatchingElements(MApplicationElement searchRoot, String xPath, Class clazz) { + return XPathContextFactory.newInstance().newContext(searchRoot).stream(xPath, clazz); + } + + // Inline the then still used part of JavaXPathContextFactoryImpl here once the + // e4.emf.xpath bundle is finally removed +} diff --git a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/fragment/impl/StringModelFragmentImpl.java b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/fragment/impl/StringModelFragmentImpl.java index fe5007880e1..b0b2ec2b310 100644 --- a/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/fragment/impl/StringModelFragmentImpl.java +++ b/bundles/org.eclipse.e4.ui.model.workbench/src/org/eclipse/e4/ui/model/fragment/impl/StringModelFragmentImpl.java @@ -18,9 +18,8 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -import org.eclipse.e4.emf.xpath.EcoreXPathContextFactory; -import org.eclipse.e4.emf.xpath.XPathContext; -import org.eclipse.e4.emf.xpath.XPathContextFactory; +import org.eclipse.core.runtime.ILog; +import org.eclipse.e4.ui.model.ModelXPathEvaluator; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.MApplicationElement; import org.eclipse.e4.ui.model.fragment.MStringModelFragment; @@ -282,10 +281,10 @@ public boolean eIsSet(int featureID) { return FEATURENAME_EDEFAULT == null ? featurename != null : !FEATURENAME_EDEFAULT.equals(featurename); case FragmentPackageImpl.STRING_MODEL_FRAGMENT__PARENT_ELEMENT_ID: return PARENT_ELEMENT_ID_EDEFAULT == null ? parentElementId != null - : !PARENT_ELEMENT_ID_EDEFAULT.equals(parentElementId); + : !PARENT_ELEMENT_ID_EDEFAULT.equals(parentElementId); case FragmentPackageImpl.STRING_MODEL_FRAGMENT__POSITION_IN_LIST: return POSITION_IN_LIST_EDEFAULT == null ? positionInList != null - : !POSITION_IN_LIST_EDEFAULT.equals(positionInList); + : !POSITION_IN_LIST_EDEFAULT.equals(positionInList); default: return super.eIsSet(featureID); } @@ -355,14 +354,13 @@ private void mergeXPath(MApplication application, List ret, if ("/".equals(xPath)) { targetElements = List.of(application); } else { - XPathContextFactory f = EcoreXPathContextFactory.newInstance(); - XPathContext xpathContext = f.newContext((EObject) application); try { - targetElements = xpathContext.stream(xPath, MApplicationElement.class).toList(); + targetElements = ModelXPathEvaluator.findMatchingElements(application, xPath, MApplicationElement.class) + .toList(); } catch (Exception ex) { targetElements = List.of(); // custom xpath functions will throw exceptions - ex.printStackTrace(); + ILog.get().error("Failed to evaluate xpath: " + xPath, ex); //$NON-NLS-1$ } } for (MApplicationElement targetElement : targetElements) { diff --git a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF index 2ea4c0a146f..5940a658411 100644 --- a/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.e4.ui.workbench/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.e4.ui.workbench;singleton:=true -Bundle-Version: 1.16.100.qualifier +Bundle-Version: 1.17.0.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java index baaec512ba8..9f3dcf3773c 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelServiceImpl.java @@ -27,12 +27,14 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; +import java.util.stream.Stream; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.core.services.events.IEventBroker; import org.eclipse.e4.core.services.log.Logger; +import org.eclipse.e4.ui.model.ModelXPathEvaluator; import org.eclipse.e4.ui.model.application.MAddon; import org.eclipse.e4.ui.model.application.MApplication; import org.eclipse.e4.ui.model.application.MApplicationElement; @@ -434,6 +436,11 @@ public List findElements(MApplicationElement searchRoot, Class clazz, return new ArrayList<>(elements); } + @Override + public Stream findMatchingElements(MApplicationElement searchRoot, String xPath, Class clazz) { + return ModelXPathEvaluator.findMatchingElements(searchRoot, xPath, clazz); + } + private Iterable findPerspectiveElements(MUIElement searchRoot, String id, Class clazz, List tagsToMatch) { diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java index e1219a063df..e7358157c52 100644 --- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java +++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/workbench/modeling/EModelService.java @@ -17,6 +17,7 @@ package org.eclipse.e4.ui.workbench.modeling; import java.util.List; +import java.util.stream.Stream; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.e4.ui.model.application.MApplicationElement; import org.eclipse.e4.ui.model.application.descriptor.basic.MPartDescriptor; @@ -279,6 +280,22 @@ List findElements(MUIElement searchRoot, String id, Class clazz, List findElements(MApplicationElement searchRoot, Class clazz, int searchFlags, Selector matcher); + /** + * Returns a stream of any elements that are matched by the specified + * {@code XPath} expression relative to the given {@code searchRoot}. + * + * @param The generic type of the returned stream + * @param searchRoot The element relative to which the {@code XPath} expression + * is evaluated. This element must be non-null. + * @param xPath the {@code XPath (XML Path Language)} expression matched + * against the root + * @param clazz The type of element to be searched for. + * @return The stream of matching elements. + * + * @since 1.17 + */ + Stream findMatchingElements(MApplicationElement searchRoot, String xPath, Class clazz); + /** * Returns the first element, recursively searching under the specified search * root (inclusive) diff --git a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesApplicationTest.java b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesApplicationTest.java index bf5c3f1b93a..37a296fb186 100644 --- a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesApplicationTest.java +++ b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesApplicationTest.java @@ -19,7 +19,6 @@ import java.util.List; -import org.eclipse.e4.emf.xpath.EcoreXPathContextFactory; import org.eclipse.e4.emf.xpath.XPathContext; import org.eclipse.e4.emf.xpath.XPathContextFactory; import org.eclipse.e4.ui.internal.workbench.E4XMIResourceFactory; @@ -43,6 +42,7 @@ import org.junit.Before; import org.junit.Test; +@SuppressWarnings({ "deprecation", "removal" }) public class ExampleQueriesApplicationTest { private ResourceSet resourceSet; @@ -69,11 +69,11 @@ public void setUp() { URI uri = URI.createPlatformPluginURI("/org.eclipse.e4.emf.xpath.test/model/Application.e4xmi", true); resource = resourceSet.getResource(uri, true); - XPathContextFactory f = EcoreXPathContextFactory.newInstance(); + XPathContextFactory f = XPathContextFactory.newInstance(); xpathContext = f.newContext(resource.getContents().get(0)); URI childUri = URI.createPlatformPluginURI("/org.eclipse.e4.emf.xpath.test/model/fragment.e4xmi", true); childResource = resourceSet.getResource(childUri, true); - xpathChildContext = f.newContext(xpathContext, childResource.getContents().get(0)); + xpathChildContext = f.newContext(childResource.getContents().get(0)); } @After diff --git a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java index 7aeb35c49c2..b78ee581aba 100644 --- a/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java +++ b/tests/org.eclipse.e4.emf.xpath.test/src/org/eclipse/e4/emf/xpath/test/ExampleQueriesTestCase.java @@ -25,7 +25,6 @@ import java.util.Iterator; import java.util.List; -import org.eclipse.e4.emf.xpath.EcoreXPathContextFactory; import org.eclipse.e4.emf.xpath.XPathContext; import org.eclipse.e4.emf.xpath.XPathContextFactory; import org.eclipse.e4.emf.xpath.XPathNotFoundException; @@ -44,6 +43,7 @@ import org.junit.Before; import org.junit.Test; +@SuppressWarnings({ "deprecation", "removal" }) public class ExampleQueriesTestCase { private ResourceSet resourceSet; @@ -61,7 +61,7 @@ public void setUp() { resourceSet.getPackageRegistry().put(XpathtestPackage.eNS_URI, XpathtestPackage.eINSTANCE); URI uri = URI.createPlatformPluginURI("/org.eclipse.e4.emf.xpath.test/model/Test.xmi", true); resource = resourceSet.getResource(uri, true); - xpathContextFactory = EcoreXPathContextFactory.newInstance(); + xpathContextFactory = XPathContextFactory.newInstance(); xpathContext = xpathContextFactory.newContext(resource.getContents().get(0)); }