Skip to content

Commit a36a2f6

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

File tree

1 file changed

+44
-12
lines changed

1 file changed

+44
-12
lines changed

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

Lines changed: 44 additions & 12 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;
@@ -77,8 +79,7 @@
7779
*/
7880
public class RangeIndexConfigAttributeCondition extends RangeIndexConfigCondition{
7981

80-
private final String attributeName;
81-
private final QName attribute;
82+
private final QName attributeName;
8283
private @Nullable final String value;
8384
private final Operator operator;
8485
private final boolean caseSensitive;
@@ -94,13 +95,23 @@ public RangeIndexConfigAttributeCondition(Element elem, NodePath parentPath) thr
9495
throw new DatabaseConfigurationException("Range index module: Attribute condition cannot be defined for an attribute:" + parentPath.toString());
9596
}
9697

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

102103
try {
103-
this.attribute = new QName(QName.extractLocalName(this.attributeName), XMLConstants.NULL_NS_URI, QName.extractPrefix(this.attributeName), ElementValue.ATTRIBUTE);
104+
final String attrLocalName = QName.extractLocalName(attributeValue);
105+
@Nullable final String attrPrefix = QName.extractPrefix(attributeValue);
106+
if (attrPrefix != null) {
107+
@Nullable final String attrNamespace = findNamespaceForPrefix(attrPrefix, (ElementImpl) elem);
108+
if (attrNamespace == null) {
109+
throw new DatabaseConfigurationException("Range index module: Missing namespace declaration for attribute qname in condition");
110+
}
111+
this.attributeName = new QName(attrLocalName, attrNamespace, attrPrefix, ElementValue.ATTRIBUTE);
112+
} else {
113+
this.attributeName = new QName(attrLocalName, XMLConstants.NULL_NS_URI, null, ElementValue.ATTRIBUTE);
114+
}
104115
} catch (final QName.IllegalQNameException e) {
105116
throw new DatabaseConfigurationException("Rand index module error: " + e.getMessage(), e);
106117
}
@@ -169,6 +180,24 @@ public RangeIndexConfigAttributeCondition(Element elem, NodePath parentPath) thr
169180

170181
}
171182

183+
private static @Nullable String findNamespaceForPrefix(final String prefix, ElementImpl contextElem) {
184+
while (contextElem != null) {
185+
final String namespace = contextElem.getNamespaceForPrefix(prefix);
186+
if (namespace != null) {
187+
return namespace;
188+
}
189+
190+
@Nullable final Node parentNode = contextElem.getParentNode();
191+
if (parentNode != null && parentNode instanceof ElementImpl) {
192+
contextElem = (ElementImpl) parentNode;
193+
} else {
194+
contextElem = null;
195+
}
196+
}
197+
198+
return null;
199+
}
200+
172201
// lazily evaluate lowercase value to convert once when needed
173202
private String getLowercaseValue() {
174203
if (this.lowercaseValue == null) {
@@ -180,15 +209,18 @@ private String getLowercaseValue() {
180209
return this.lowercaseValue;
181210
}
182211

183-
184212
@Override
185-
public boolean matches(Node node) {
186-
187-
if (node.getNodeType() == Node.ELEMENT_NODE && matchValue(((Element)node).getAttribute(attributeName))) {
188-
return true;
213+
public boolean matches(final Node node) {
214+
final String attrValue;
215+
if (attributeName.hasNamespace()) {
216+
attrValue = ((Element) node).getAttributeNS(attributeName.getNamespaceURI(), attributeName.getLocalPart());
217+
} else {
218+
attrValue = ((Element) node).getAttribute(attributeName.getLocalPart());
189219
}
190220

191-
return false;
221+
return node.getNodeType() == Node.ELEMENT_NODE
222+
&& matchValue(attrValue);
223+
192224
}
193225

194226
private boolean matchValue(String testValue) {
@@ -365,7 +397,7 @@ public boolean find(Predicate predicate) {
365397

366398
if (qname.getNameType() == ElementValue.ATTRIBUTE
367399
&& operator.equals(this.operator)
368-
&& qname.equals(this.attribute)
400+
&& qname.equals(attributeName)
369401
&& valueTypeMatches
370402
&& foundValue.equals(requiredValue)) {
371403

0 commit comments

Comments
 (0)