@@ -137,6 +137,8 @@ public class NodeProxy implements NodeSet, NodeValue, NodeHandle, DocumentSet, C
137
137
138
138
private final Expression expression ;
139
139
140
+ private @ Nullable WeakReference <Node > cachedNode = null ;
141
+
140
142
/**
141
143
* Creates a new <code>NodeProxy</code> instance.
142
144
*
@@ -233,6 +235,10 @@ public NodeProxy(final Expression expression, final DocumentImpl doc, final Node
233
235
this .nodeId = nodeId ;
234
236
}
235
237
238
+ private void invalidateCachedNode () {
239
+ this .cachedNode = null ;
240
+ }
241
+
236
242
public void update (final ElementImpl element ) {
237
243
invalidateCachedNode ();
238
244
this .doc = element .getOwnerDocument ();
@@ -322,6 +328,7 @@ public NodeId getNodeId() {
322
328
@ Override
323
329
public QName getQName () {
324
330
if (qname == null ) {
331
+ // NOTE(AR) get the node from the database, which will also update the `qname`
325
332
getNode ();
326
333
}
327
334
return qname ;
@@ -447,14 +454,7 @@ public DocumentImpl getOwnerDocument() {
447
454
* @return a <code>boolean</code> value
448
455
*/
449
456
public boolean isDocument () {
450
- return nodeType == Node .DOCUMENT_NODE ;
451
- }
452
-
453
-
454
- private @ Nullable WeakReference <Node > cachedNode = null ;
455
-
456
- private void invalidateCachedNode () {
457
- this .cachedNode = null ;
457
+ return getNodeType () == Node .DOCUMENT_NODE ;
458
458
}
459
459
460
460
/**
@@ -464,7 +464,8 @@ private void invalidateCachedNode() {
464
464
*/
465
465
@ Override
466
466
public Node getNode () {
467
- if (isDocument ()) {
467
+ // NOTE(AR) we don't call isDocument() or getNodeType() here as it would call back to getNode() and cause a StackOverflowError
468
+ if (nodeType == Node .DOCUMENT_NODE ) {
468
469
return doc ;
469
470
}
470
471
@@ -481,7 +482,7 @@ public Node getNode() {
481
482
this .nodeType = realNode .getNodeType ();
482
483
this .qname = realNode .getQName ();
483
484
}
484
- cachedNode = new WeakReference <>(realNode );
485
+ this . cachedNode = new WeakReference <>(realNode );
485
486
node = realNode ;
486
487
}
487
488
@@ -490,6 +491,10 @@ public Node getNode() {
490
491
491
492
@ Override
492
493
public short getNodeType () {
494
+ if (nodeType == UNKNOWN_NODE_TYPE ) {
495
+ // NOTE(AR) get the node from the database, which will also update the `nodeType`
496
+ getNode ();
497
+ }
493
498
return nodeType ;
494
499
}
495
500
@@ -851,12 +856,9 @@ public void toSAX(final DBBroker broker, final ContentHandler handler, final Pro
851
856
852
857
@ Override
853
858
public void copyTo (final DBBroker broker , final DocumentBuilderReceiver receiver ) throws SAXException {
854
- NodeImpl node = null ;
855
- if (nodeType < 0 ) {
856
- node = (NodeImpl ) getNode ();
857
- }
858
- if (nodeType == Node .ATTRIBUTE_NODE ) {
859
- final AttrImpl attr = (node == null ? (AttrImpl ) getNode () : (AttrImpl ) node );
859
+ final Node node = getNode ();
860
+ if (node .getNodeType () == Node .ATTRIBUTE_NODE ) {
861
+ final AttrImpl attr = (AttrImpl ) node ;
860
862
receiver .attribute (attr .getQName (), attr .getValue ());
861
863
} else {
862
864
receiver .addReferenceNode (this );
@@ -1344,6 +1346,7 @@ public NodeSet selectFollowing(final NodeSet following, final int position, fina
1344
1346
1345
1347
@ Override
1346
1348
public NodeSet directSelectAttribute (final DBBroker broker , final NodeTest test , final int contextId ) {
1349
+ final short nodeType = getNodeType ();
1347
1350
if (nodeType != UNKNOWN_NODE_TYPE && nodeType != Node .ELEMENT_NODE ) {
1348
1351
return NodeSet .EMPTY_SET ;
1349
1352
}
@@ -1387,6 +1390,7 @@ public NodeSet directSelectAttribute(final DBBroker broker, final NodeTest test,
1387
1390
}
1388
1391
1389
1392
public NodeSet directSelectChild (final QName qname , final int contextId ) {
1393
+ final short nodeType = getNodeType ();
1390
1394
if (nodeType != UNKNOWN_NODE_TYPE && nodeType != Node .ELEMENT_NODE ) {
1391
1395
return NodeSet .EMPTY_SET ;
1392
1396
}
@@ -1609,6 +1613,7 @@ public boolean equalDocs(final DocumentSet other) {
1609
1613
1610
1614
@ Override
1611
1615
public boolean directMatchAttribute (final DBBroker broker , final NodeTest test , final int contextId ) {
1616
+ final short nodeType = getNodeType ();
1612
1617
if (nodeType != UNKNOWN_NODE_TYPE && nodeType != Node .ELEMENT_NODE ) {
1613
1618
return false ;
1614
1619
}
@@ -1638,6 +1643,7 @@ public boolean directMatchAttribute(final DBBroker broker, final NodeTest test,
1638
1643
}
1639
1644
1640
1645
public boolean directMatchChild (final QName qname , final int contextId ) {
1646
+ final short nodeType = getNodeType ();
1641
1647
if (nodeType != UNKNOWN_NODE_TYPE && nodeType != Node .ELEMENT_NODE ) {
1642
1648
return false ;
1643
1649
}
0 commit comments