@@ -71,32 +71,43 @@ public XPathContext newContext(XPathContext parentContext, T contextBean) {
71
71
if (!(contextBean instanceof EObject rootObject )) {
72
72
throw new IllegalArgumentException ();
73
73
}
74
- // TODO: consider parent-context (may be null). Require the context-bean to be
75
- // from the same resource? Then we can also reuse all maps and the XPath object
76
-
77
- DocumentBuilder documentBuilder ;
78
- try {
79
- documentBuilder = DocumentBuilderFactory .newDefaultInstance ().newDocumentBuilder ();
80
- } catch (ParserConfigurationException e ) {
81
- throw new IllegalStateException (e );
74
+ XPath xpath ;
75
+ DOMMapping domMapping ;
76
+ Element rootElement = null ;
77
+
78
+ if (parentContext != null ) {
79
+ EObjectContext parent = (EObjectContext ) parentContext ;
80
+ xpath = parent .xpath ;
81
+ rootElement = parent .domMapping .getElement (contextBean );
82
+ } else {
83
+ xpath = XPATH_FACTORY .newXPath ();
82
84
}
83
- Document document = documentBuilder .newDocument ();
84
85
85
- XPath xpath = XPATH_FACTORY .newXPath ();
86
- DefaultDOMHandlerImpl domMapping = new DefaultDOMHandlerImpl ();
87
- Element rootElement = createElement (rootObject , document , domMapping );
88
- xpath .setNamespaceContext (createNamespaceContext (rootElement ));
86
+ if (rootElement != null ) {
87
+ domMapping = ((EObjectContext ) parentContext ).domMapping ;
88
+ } else {
89
+ DocumentBuilder documentBuilder ;
90
+ try {
91
+ documentBuilder = DocumentBuilderFactory .newDefaultInstance ().newDocumentBuilder ();
92
+ } catch (ParserConfigurationException e ) {
93
+ throw new IllegalStateException (e );
94
+ }
95
+ Document document = documentBuilder .newDocument ();
89
96
97
+ domMapping = new DOMMapping ();
98
+ rootElement = createElement (rootObject , document , domMapping );
99
+ xpath .setNamespaceContext (createNamespaceContext (rootElement ));
100
+ }
90
101
return new EObjectContext (rootElement , domMapping , xpath );
91
102
}
92
103
93
104
private static class EObjectContext implements XPathContext {
94
105
95
106
private final XPath xpath ;
96
107
private final Element rootElement ;
97
- private final DefaultDOMHandlerImpl domMapping ;
108
+ private final DOMMapping domMapping ;
98
109
99
- private EObjectContext (Element rootElement , DefaultDOMHandlerImpl domMapping , XPath xpath ) {
110
+ private EObjectContext (Element rootElement , DOMMapping domMapping , XPath xpath ) {
100
111
this .rootElement = rootElement ;
101
112
this .domMapping = domMapping ;
102
113
this .xpath = xpath ;
@@ -191,7 +202,7 @@ private static Node getSingleNodeArgument(List<?> args) throws XPathFunctionExce
191
202
}
192
203
}
193
204
194
- private static Element createElement (EObject eObject , Document document , DefaultDOMHandlerImpl domMapper ) {
205
+ private static Element createElement (EObject eObject , Document document , DOMMapping domMapper ) {
195
206
new XMLSaveImpl (Map .of (), new XMIHelperImpl (), "UTF-8" ).save (null , document ,
196
207
Map .of (XMLResource .OPTION_ROOT_OBJECTS , List .of (eObject )), domMapper );
197
208
return document .getDocumentElement ();
@@ -225,6 +236,18 @@ public Iterator<String> getPrefixes(String namespaceURI) {
225
236
};
226
237
}
227
238
239
+ private static class DOMMapping extends DefaultDOMHandlerImpl {
240
+
241
+ public Element getElement (Object object ) {
242
+ for (Map .Entry <Node , Object > entry : nodeToObject .entrySet ()) {
243
+ if (Objects .equals (entry .getValue (), object )) {
244
+ return (Element ) entry .getKey ();
245
+ }
246
+ }
247
+ return null ;
248
+ }
249
+ }
250
+
228
251
private static Optional <Object > reconstructReferenceList (EObject first , String xpath , Iterator <Object > iterator ) {
229
252
EReference containment = first .eContainmentFeature ();
230
253
if (containment != null && containment .isMany () && xpath .endsWith ("/" + containment .getName ())) {
0 commit comments