Skip to content

Commit 3906ade

Browse files
committed
[bugfix] Reference nodes in the in-memory DOM (Memtree) should be transparent to the org.w3c.dom API
Closes eXist-db/exist#5682
1 parent 18d76d3 commit 3906ade

File tree

4 files changed

+261
-30
lines changed

4 files changed

+261
-30
lines changed

exist-core/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,7 @@
683683
<include>src/test/java/org/exist/xquery/value/DateTimeTypesTest.java</include>
684684
<include>src/test/java/org/exist/xquery/functions/fn/FunXmlToJsonTest.java</include>
685685
<include>src/test/java/org/exist/xquery/functions/fn/ParsingFunctionsTest.java</include>
686+
<include>src/test/java/org/exist/xquery/functions/fn/transform/FunTransformITTest.java</include>
686687
<include>src/test/java/org/exist/xquery/functions/xmldb/XMLDBStoreTest.java</include>
687688
<include>src/test/resources-filtered/org/exist/xquery/import-from-pkg-test.conf.xml</include>
688689
</includes>
@@ -726,7 +727,9 @@
726727
<include>src/main/java/org/exist/collections/triggers/CollectionTrigger.java</include>
727728
<include>src/main/java/org/exist/collections/triggers/DocumentTrigger.java</include>
728729
<include>src/main/java/org/exist/config/Configuration.java</include>
730+
<include>src/main/java/org/exist/dom/memtree/DocumentImpl.java</include>
729731
<include>src/main/java/org/exist/dom/memtree/ElementImpl.java</include>
732+
<include>src/main/java/org/exist/dom/memtree/MemTreeBuilder.java</include>
730733
<include>src/main/java/org/exist/dom/persistent/DocumentImpl.java</include>
731734
<include>src/main/java/org/exist/dom/persistent/DocumentSet.java</include>
732735
<include>src/main/java/org/exist/dom/persistent/ElementImpl.java</include>
@@ -855,7 +858,9 @@
855858
<exclude>src/main/java/org/exist/collections/triggers/CollectionTrigger.java</exclude>
856859
<exclude>src/main/java/org/exist/collections/triggers/DocumentTrigger.java</exclude>
857860
<exclude>src/main/java/org/exist/config/Configuration.java</exclude>
861+
<exclude>src/main/java/org/exist/dom/memtree/DocumentImpl.java</exclude>
858862
<exclude>src/main/java/org/exist/dom/memtree/ElementImpl.java</exclude>
863+
<exclude>src/main/java/org/exist/dom/memtree/MemTreeBuilder.java</exclude>
859864
<exclude>src/main/java/org/exist/dom/persistent/DocumentImpl.java</exclude>
860865
<exclude>src/main/java/org/exist/dom/persistent/DocumentSet.java</exclude>
861866
<exclude>src/main/java/org/exist/dom/persistent/ElementImpl.java</exclude>
@@ -911,6 +916,7 @@
911916
<exclude>src/main/java/org/exist/xquery/functions/fn/LoadXQueryModule.java</exclude>
912917
<exclude>src/main/java/org/exist/xquery/functions/fn/ParsingFunctions.java</exclude>
913918
<exclude>src/test/java/org/exist/xquery/functions/fn/ParsingFunctionsTest.java</exclude>
919+
<exclude>src/test/java/org/exist/xquery/functions/fn/transform/FunTransformITTest.java</exclude>
914920
<exclude>src/main/java/org/exist/xquery/functions/system/GetUptime.java</exclude>
915921
<exclude>src/main/java/org/exist/xquery/functions/system/Shutdown.java</exclude>
916922
<exclude>src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java</exclude>

exist-core/src/main/java/org/exist/dom/memtree/DocumentImpl.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -47,6 +71,7 @@
4771
import org.w3c.dom.*;
4872
import org.xml.sax.SAXException;
4973

74+
import javax.annotation.Nullable;
5075
import javax.xml.XMLConstants;
5176
import java.util.Arrays;
5277
import java.util.Objects;
@@ -222,11 +247,11 @@ public boolean isExplicitlyCreated() {
222247
return explicitlyCreated;
223248
}
224249

225-
public int addNode(final short kind, final short level, final QName qname) {
226-
if(nodeKind == null) {
250+
public int addNode(final short kind, final short level, @Nullable final QName qname) {
251+
if (nodeKind == null) {
227252
init();
228253
}
229-
if(size == nodeKind.length) {
254+
if (size == nodeKind.length) {
230255
grow();
231256
}
232257
nodeKind[size] = kind;
@@ -318,10 +343,10 @@ public void appendChars(final int nodeNum, final CharSequence s) {
318343
}
319344

320345
public void addReferenceNode(final int nodeNum, final NodeProxy proxy) {
321-
if(nodeKind == null) {
346+
if (nodeKind == null) {
322347
init();
323348
}
324-
if((references == null) || (nextReferenceIdx == references.length)) {
349+
if (references == null || nextReferenceIdx == references.length) {
325350
growReferences();
326351
}
327352
references[nextReferenceIdx] = proxy;
@@ -513,14 +538,16 @@ public NodeImpl getNamespaceNode(final int nodeNum) throws DOMException {
513538
}
514539

515540
public NodeImpl getNode(final int nodeNum) throws DOMException {
516-
if(nodeNum == 0) {
541+
if (nodeNum == 0) {
517542
return this;
518543
}
519-
if(nodeNum >= size) {
544+
545+
if (nodeNum >= size) {
520546
throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, "node not found");
521547
}
522-
final NodeImpl node;
523-
switch(nodeKind[nodeNum]) {
548+
549+
final NodeImpl<?> node;
550+
switch (nodeKind[nodeNum]) {
524551
case Node.ELEMENT_NODE:
525552
node = new ElementImpl(getExpression(), this, nodeNum);
526553
break;

exist-core/src/main/java/org/exist/dom/memtree/MemTreeBuilder.java

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -245,22 +269,22 @@ public void endElement() {
245269
public int addReferenceNode(final NodeProxy proxy) {
246270
final int lastNode = doc.getLastNode();
247271

248-
if((lastNode > 0) && (level == doc.getTreeLevel(lastNode))) {
272+
if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
249273

250-
if((doc.getNodeType(lastNode) == Node.TEXT_NODE) && (proxy.getNodeType() == Node.TEXT_NODE)) {
274+
if (doc.getNodeType(lastNode) == Node.TEXT_NODE && proxy.getNodeType() == Node.TEXT_NODE) {
251275

252276
// if the last node is a text node, we have to append the
253277
// characters to this node. XML does not allow adjacent text nodes.
254278
doc.appendChars(lastNode, proxy.getNodeValue());
255279
return lastNode;
256280
}
257281

258-
if(doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
282+
if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
259283

260284
// check if the previous node is a reference node. if yes, check if it is a text node
261285
final int p = doc.alpha[lastNode];
262286

263-
if((doc.references[p].getNodeType() == Node.TEXT_NODE) && (proxy.getNodeType() == Node.TEXT_NODE)) {
287+
if (doc.references[p].getNodeType() == Node.TEXT_NODE && proxy.getNodeType() == Node.TEXT_NODE) {
264288

265289
// found a text node reference. create a new char sequence containing
266290
// the concatenated text of both nodes
@@ -306,22 +330,22 @@ public int addAttribute(final QName qname, final String value) {
306330
public int characters(final char[] ch, final int start, final int len) {
307331
final int lastNode = doc.getLastNode();
308332

309-
if((lastNode > 0) && (level == doc.getTreeLevel(lastNode))) {
333+
if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
310334

311-
if(doc.getNodeType(lastNode) == Node.TEXT_NODE) {
335+
if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
312336

313-
// if the last node is a text node, we have to append the
337+
// if the last node is a Text or CDATA node, we have to append the
314338
// characters to this node. XML does not allow adjacent text nodes.
315339
doc.appendChars(lastNode, ch, start, len);
316340
return lastNode;
317341
}
318342

319-
if(doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
343+
if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
320344

321-
// check if the previous node is a reference node. if yes, check if it is a text node
345+
// check if the previous node is a reference node. if yes, check if it is a Text or CDATA node
322346
final int p = doc.alpha[lastNode];
323347

324-
if(doc.references[p].getNodeType() == Node.TEXT_NODE) {
348+
if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
325349

326350
// found a text node reference. create a new char sequence containing
327351
// the concatenated text of both nodes
@@ -347,28 +371,28 @@ public int characters(final char[] ch, final int start, final int len) {
347371
* @return the node number of the created node, -1 if no node was created
348372
*/
349373
public int characters(final CharSequence s) {
350-
if(s == null) {
374+
if (s == null) {
351375
return -1;
352376
}
353377

354378
final int lastNode = doc.getLastNode();
355379

356-
if((lastNode > 0) && (level == doc.getTreeLevel(lastNode))) {
380+
if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
357381

358-
if((doc.getNodeType(lastNode) == Node.TEXT_NODE) || (doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE)) {
382+
if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
359383

360-
// if the last node is a text node, we have to append the
384+
// if the last node is a Text or CDATA node, we have to append the
361385
// characters to this node. XML does not allow adjacent text nodes.
362386
doc.appendChars(lastNode, s);
363387
return lastNode;
364388
}
365389

366-
if(doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
390+
if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
367391

368-
// check if the previous node is a reference node. if yes, check if it is a text node
369392
final int p = doc.alpha[lastNode];
393+
// check if the previous node is a reference node. if yes, check if it is a Text or CDATA node
370394

371-
if((doc.references[p].getNodeType() == Node.TEXT_NODE) || (doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE)) {
395+
if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
372396

373397
// found a text node reference. create a new char sequence containing
374398
// the concatenated text of both nodes
@@ -404,22 +428,22 @@ public int comment(final char[] ch, final int start, final int len) {
404428
public int cdataSection(final CharSequence data) {
405429
final int lastNode = doc.getLastNode();
406430

407-
if((lastNode > 0) && (level == doc.getTreeLevel(lastNode))) {
431+
if (lastNode > 0 && level == doc.getTreeLevel(lastNode)) {
408432

409-
if((doc.getNodeType(lastNode) == Node.TEXT_NODE) || (doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE)) {
433+
if (doc.getNodeType(lastNode) == Node.TEXT_NODE || doc.getNodeType(lastNode) == Node.CDATA_SECTION_NODE) {
410434

411435
// if the last node is a text node, we have to append the
412436
// characters to this node. XML does not allow adjacent text nodes.
413437
doc.appendChars(lastNode, data);
414438
return lastNode;
415439
}
416440

417-
if(doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
441+
if (doc.getNodeType(lastNode) == NodeImpl.REFERENCE_NODE) {
418442

419443
// check if the previous node is a reference node. if yes, check if it is a text node
420444
final int p = doc.alpha[lastNode];
421445

422-
if((doc.references[p].getNodeType() == Node.TEXT_NODE) || (doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE)) {
446+
if (doc.references[p].getNodeType() == Node.TEXT_NODE || doc.references[p].getNodeType() == Node.CDATA_SECTION_NODE) {
423447

424448
// found a text node reference. create a new char sequence containing
425449
// the concatenated text of both nodes

0 commit comments

Comments
 (0)