Skip to content

Commit 59debd1

Browse files
committed
[bugfix] Handle QNames correctly in attribute names within conditions of the Range Index config
Closes eXist-db/exist#5189
1 parent 3df8cc0 commit 59debd1

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

extensions/indexes/range/src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
package org.exist.indexing.range;
4747

4848
import org.exist.dom.QName;
49+
import org.exist.dom.persistent.ElementImpl;
50+
import org.exist.dom.persistent.NodeImpl;
4951
import org.exist.storage.ElementValue;
5052
import org.exist.storage.NodePath;
5153
import org.exist.util.DatabaseConfigurationException;
@@ -78,8 +80,7 @@
7880
*/
7981
public class RangeIndexConfigAttributeCondition extends RangeIndexConfigCondition{
8082

81-
private final String attributeName;
82-
private final QName attribute;
83+
private final QName attributeName;
8384
private @Nullable final String value;
8485
private final Operator operator;
8586
private final boolean caseSensitive;
@@ -96,13 +97,23 @@ public RangeIndexConfigAttributeCondition(final Element elem, final NodePath par
9697
"Range index module: Attribute condition cannot be defined for an attribute:" + parentPath);
9798
}
9899

99-
this.attributeName = elem.getAttribute("attribute");
100-
if (this.attributeName.isEmpty()) {
100+
final String attributeValue = elem.getAttribute("attribute");
101+
if (attributeValue.isEmpty()) {
101102
throw new DatabaseConfigurationException("Range index module: Empty or no attribute qname in condition");
102103
}
103104

104105
try {
105-
this.attribute = new QName(QName.extractLocalName(this.attributeName), XMLConstants.NULL_NS_URI, QName.extractPrefix(this.attributeName), ElementValue.ATTRIBUTE);
106+
final String attrLocalName = QName.extractLocalName(attributeValue);
107+
@Nullable final String attrPrefix = QName.extractPrefix(attributeValue);
108+
if (attrPrefix != null) {
109+
@Nullable final String attrNamespace = findNamespaceForPrefix(attrPrefix, (ElementImpl) elem);
110+
if (attrNamespace == null) {
111+
throw new DatabaseConfigurationException("Range index module: Missing namespace declaration for attribute qname in condition");
112+
}
113+
this.attributeName = new QName(attrLocalName, attrNamespace, attrPrefix, ElementValue.ATTRIBUTE);
114+
} else {
115+
this.attributeName = new QName(attrLocalName, XMLConstants.NULL_NS_URI, null, ElementValue.ATTRIBUTE);
116+
}
106117
} catch (final QName.IllegalQNameException e) {
107118
throw new DatabaseConfigurationException("Rand index module error: " + e.getMessage(), e);
108119
}
@@ -171,6 +182,24 @@ public RangeIndexConfigAttributeCondition(final Element elem, final NodePath par
171182

172183
}
173184

185+
private static @Nullable String findNamespaceForPrefix(final String prefix, ElementImpl contextElem) {
186+
while (contextElem != null) {
187+
final String namespace = contextElem.getNamespaceForPrefix(prefix);
188+
if (namespace != null) {
189+
return namespace;
190+
}
191+
192+
@Nullable final Node parentNode = contextElem.getParentNode();
193+
if (parentNode != null && parentNode instanceof ElementImpl) {
194+
contextElem = (ElementImpl) parentNode;
195+
} else {
196+
contextElem = null;
197+
}
198+
}
199+
200+
return null;
201+
}
202+
174203
// lazily evaluate lowercase value to convert once when needed
175204
private String getLowercaseValue() {
176205
if (this.lowercaseValue == null) {
@@ -184,8 +213,16 @@ private String getLowercaseValue() {
184213

185214
@Override
186215
public boolean matches(final Node node) {
216+
final String attrValue;
217+
if (attributeName.hasNamespace()) {
218+
attrValue = ((Element) node).getAttributeNS(attributeName.getNamespaceURI(), attributeName.getLocalPart());
219+
} else {
220+
attrValue = ((Element) node).getAttribute(attributeName.getLocalPart());
221+
}
222+
187223
return node.getNodeType() == Node.ELEMENT_NODE
188-
&& matchValue(((Element) node).getAttribute(attributeName));
224+
&& matchValue(attrValue);
225+
189226
}
190227

191228
private boolean matchValue(final String testValue) {
@@ -312,7 +349,7 @@ public boolean find(final Predicate predicate) {
312349
}
313350

314351
final QName qname = testStep.getTest().getName();
315-
if (qname.getNameType() != ElementValue.ATTRIBUTE || !qname.equals(attribute)) {
352+
if (qname.getNameType() != ElementValue.ATTRIBUTE || !qname.equals(attributeName)) {
316353
return false;
317354
}
318355

0 commit comments

Comments
 (0)