Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] [E4 Xpath] Replace apache.commons.jxpath by javax.xml.xpath #2387

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions bundles/org.eclipse.e4.emf.xpath/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Bundle-SymbolicName: org.eclipse.e4.emf.xpath
Bundle-Version: 0.5.0.qualifier
Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.eclipse.emf.ecore;bundle-version="2.35.0",
org.eclipse.emf.ecore.xmi;bundle-version="2.35.0",
org.eclipse.core.runtime;bundle-version="3.29.0"
Export-Package: org.eclipse.e4.emf.internal.xpath;x-internal:=true,
org.eclipse.e4.emf.internal.xpath.helper;x-friends:="org.eclipse.e4.emf.xpath.test,org.eclipse.e4.ui.model.workbench,org.eclipse.e4.ui.workbench",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.eclipse.e4.emf.xpath;

import org.eclipse.e4.emf.xpath.internal.java.JavaXPathFactoryImpl;
import org.eclipse.emf.ecore.EObject;

/**
* @since 0.5
*/
public abstract class JavaXPathFactory<T> {
/**
* Creates a new XPathContext with the specified object as the root node.
*
* @param contextBean Object
* @return XPathContext
*/
public abstract XPathContext newContext(T contextBean);

/**
* Creates a new XPathContext with the specified bean as the root node and the
* specified parent context. Variables defined in a parent context can be
* referenced in XPaths passed to the child context.
*
* @param parentContext parent context
* @param contextBean Object
* @return XPathContext
*/
public abstract XPathContext newContext(XPathContext parentContext, T contextBean);

/**
* @param <Type> the object type the xpath is created for

Check warning on line 30 in bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/JavaXPathFactory.java

View check run for this annotation

Jenkins - Eclipse Platform / JavaDoc

JavaDoc @param

ERROR: @param name not found
* @return Create a new XPath-Factory
*/
public static XPathContextFactory<EObject> newInstance() {
return new JavaXPathFactoryImpl<>();
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package org.eclipse.e4.emf.xpath.internal.java;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathEvaluationResult;
import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathNodes;

import org.eclipse.e4.emf.xpath.XPathContext;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;

public class EObjectContext implements XPathContext {
private final String PROXY_KEY = "EObjectContext.Proxy";
private final Map<EObject, Node> proxy2node;
private final EObjectContext parentContext;
private final Document root;
private XMLHelper xml;

public EObjectContext() throws ParserConfigurationException {
this(null);
}

public EObjectContext(EObjectContext parentContext) throws ParserConfigurationException {
this.proxy2node = new HashMap<>();
this.parentContext = parentContext;
if (parentContext == null) {
this.root = DocumentBuilderFactory.newDefaultInstance().newDocumentBuilder().newDocument();
} else {
this.root = parentContext.root;
}
}

@Override
public Object getValue(String xpath) {
Iterator<Object> iterate = iterate(xpath);
return iterate.hasNext() ? iterate.next() : null;
}

@Override
public <T> T getValue(String xpath, Class<T> requiredType) {
return requiredType.cast(getValue(xpath));
}

@Override
@SuppressWarnings("unchecked")
public <T> Iterator<T> iterate(String xpath) {
return (Iterator<T>) stream(xpath, Object.class).iterator();
}

@Override
public <T> Stream<T> stream(String path, Class<T> type) {
try {
XPathFactory factory = XPathFactory.newInstance();
// factory.setXPathFunctionResolver((functionName, arity) -> null);
// factory.setXPathVariableResolver(e -> null);
XPath xpath = factory.newXPath();
/*
EObjectNodePointer item = new EObjectNodePointer(contextObject);
XPathEvaluationResult<?> evaluateExpression = xpath.evaluateExpression(path, item);
XPathNodes value1 = (XPathNodes) evaluateExpression.value();
if (value1.size() > 0) {
Node node = value1.get(0);
System.out.println(node);
}*/

// path = "/Application/TrimmedWindow";
XPathEvaluationResult<?> result1 = xpath.evaluateExpression(path, root);
XPathNodes nodes2 = (XPathNodes) result1.value();
if (nodes2.size() > 0) {
Node node = nodes2.get(0);

System.out.println(node);
}

prettyPrint();

XPathExpression expr = xpath.compile(path);
XPathEvaluationResult result = expr.evaluateExpression(root, XPathEvaluationResult.class);

Check warning on line 102 in bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/EObjectContext.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unchecked Raw

NORMAL: should be parameterized XPathEvaluationResult is a raw type. References to generic type XPathEvaluationResult
XPathResultType type2 = result.type();

Check warning on line 103 in bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/EObjectContext.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

NORMAL: The value of the local variable type2 is not used
Object value = result.value();

Check warning on line 104 in bundles/org.eclipse.e4.emf.xpath/src/org/eclipse/e4/emf/xpath/internal/java/EObjectContext.java

View check run for this annotation

Jenkins - Eclipse Platform / Compiler and API Tools

Unnecessary Code

NORMAL: The value of the local variable value is not used

NodeList nodes1 = (NodeList) expr.evaluate(root, XPathConstants.NODESET);
XPathNodes nodes = expr.evaluateExpression(root, XPathNodes.class);

System.out.println(nodes1.getLength());
System.out.println(nodes.size());

Stream<Node> stream = StreamSupport.stream(Spliterators.spliterator(nodes.iterator(), nodes.size(), 0),
false);
return stream.map(this::getProxy).map(type::cast);
} catch (Exception e1) {
throw new IllegalStateException(e1);
}
}

private void prettyPrint() {
final DOMImplementation implementation = root.getImplementation();
final DOMImplementationLS domImplementation = (DOMImplementationLS) implementation;
final LSSerializer serial = domImplementation.createLSSerializer();
serial.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);

final String writeToString = serial.writeToString(root);
System.out.println(writeToString);
}

protected Element getNode(EObject proxy) {
return (Element) proxy2node.get(proxy);
}

protected EObject getProxy(Node element) {
return (EObject) element.getUserData(PROXY_KEY);
}

protected Element addRoot(EObject eObject) {
// TODO What about other types of resources?
xml = new XMLHelperImpl((XMLResource) eObject.eResource());
Element object = createElement(eObject);
if (parentContext == null) {
root.appendChild(object);
} else {
Element parentObject = getNode(eObject.eContainer());
parentObject.appendChild(object);
}
return object;
}

protected Element add(EObject eChildObject, EObject eParentObject) {
Element childObject = createElement(eChildObject);
Node parentObject = proxy2node.get(eParentObject);
parentObject.appendChild(childObject);
return childObject;
}

private Element createElement(EObject eObject) {
// TODO: Better way to get the "root" QName
String qName = "application";
if (eObject.eContainingFeature() != null) {
qName = xml.getQName(eObject.eContainingFeature());
}
Element object = root.createElement(qName);
object.setUserData(PROXY_KEY, eObject, null);
proxy2node.put(eObject, object);
List<EAttribute> eAttributes = eObject.eClass().getEAllAttributes();
for (EAttribute eAttribute : eAttributes) {
if (eObject.eIsSet(eAttribute)) {
Object value = eObject.eGet(eAttribute);
String stringValue = EcoreUtil.convertToString(eAttribute.getEAttributeType(), value);
object.setAttribute(eAttribute.getName(), stringValue);
}
}
return object;
}
}
Loading
Loading