Skip to content

Commit 867bdbc

Browse files
[refactor] Correct wrong types, add documentation, add clearing of cached URI results, and add test for non-existing URI
1 parent f497d51 commit 867bdbc

File tree

3 files changed

+57
-26
lines changed

3 files changed

+57
-26
lines changed

exist-core/src/main/java/org/exist/xquery/XQueryContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,6 @@ public class XQueryContext implements BinaryValueManager, Context {
144144
public static final String HTTP_REQ_ATTR_USER = "xquery.user";
145145
public static final String HTTP_REQ_ATTR_PASS = "xquery.password";
146146

147-
public static final String DEFAULT_URI_COLLECTION = "/db";
148-
149147
// Static namespace/prefix mappings
150148
protected Map<String, String> staticNamespaces = new HashMap<>();
151149

@@ -1407,6 +1405,8 @@ public void reset(final boolean keepGlobals) {
14071405
callStack.clear();
14081406
protectedDocuments = null;
14091407

1408+
cachedUriCollectionResults.clear();
1409+
14101410
if (!keepGlobals) {
14111411
globalVariables.clear();
14121412
}

exist-core/src/main/java/org/exist/xquery/functions/fn/FunUriCollection.java

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.exist.security.PermissionDeniedException;
2929
import org.exist.storage.lock.Lock;
3030
import org.exist.util.LockException;
31+
import org.exist.util.PatternFactory;
3132
import org.exist.xmldb.XmldbURI;
3233
import org.exist.xquery.*;
3334
import org.exist.xquery.value.*;
@@ -44,10 +45,29 @@ public class FunUriCollection extends BasicFunction {
4445

4546
private static final String FN_NAME = "uri-collection";
4647
private static final String FN_DESCRIPTION = "Returns a sequence of xs:anyURI values that represent the URIs in a URI collection.";
47-
private static final FunctionReturnSequenceType FN_RETURN = returnsOptMany(Type.STRING,
48+
private static final FunctionReturnSequenceType FN_RETURN = returnsOptMany(Type.ANY_URI,
4849
"the default URI collection, if $arg is not specified or is an empty sequence, " +
4950
"or the sequence of URIs that correspond to the supplied URI");
50-
private static final FunctionParameterSequenceType ARG = optParam("arg", Type.STRING, "The base-URI property from the static context, or an empty sequence");
51+
private static final FunctionParameterSequenceType ARG = optParam("arg", Type.STRING,
52+
"An xs:string identifying a URI Collection. " +
53+
"The argument is interpreted as either an absolute xs:anyURI, or a relative xs:anyURI resolved " +
54+
"against the base-URI property from the static context. In eXist-db this function consults the " +
55+
"query hierarchy of the database. Query String parameters may be provided to " +
56+
"control the URIs returned by this function. " +
57+
"The parameter `match` may be used to provide a Regular Expression against which the result " +
58+
"sequence of URIs are filtered. " +
59+
"The parameter `content-type` may be used to determine the Internet Media Type (or generally " +
60+
"whether XML, Binary, and/or (Sub) Collection) URIs that are returned in the result sequence; " +
61+
"the special values: 'application/vnd.existdb.collection' includes (Sub) Collections, " +
62+
"'application/vnd.existdb.document' includes any document, " +
63+
"'application/vnd.existdb.document+xml' includes only XML documents, and " +
64+
"'application/vnd.existdb.document+binary' includes only Binary documents. By default, " +
65+
"`content-type=application/vnd.existdb.collection,application/vnd.existdb.document` " +
66+
"(i.e. all Collections and Documents). " +
67+
"The parameter `stable` may be used to determine if the function is deterministic. " +
68+
"By default `stable=yes` to ensure that the same results are returned by each call within the same " +
69+
"query."
70+
);
5171
public static final FunctionSignature[] FS_URI_COLLECTION_SIGNATURES = functionSignatures(
5272
FN_NAME,
5373
FN_DESCRIPTION,
@@ -87,13 +107,9 @@ public FunUriCollection(final XQueryContext context, final FunctionSignature sig
87107
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
88108
final Sequence result;
89109
if (args.length == 0 || args[0].isEmpty() || args[0].toString().isEmpty()) {
90-
if (XQueryContext.DEFAULT_URI_COLLECTION != null && XQueryContext.DEFAULT_URI_COLLECTION.length() > 0) {
91-
result = new StringValue(XQueryContext.DEFAULT_URI_COLLECTION);
92-
} else {
93-
throw new XPathException(this, ErrorCodes.FODC0002, "No URI is supplied and default resource collection is absent.");
94-
}
110+
result = new AnyURIValue(XmldbURI.ROOT_COLLECTION);
95111
} else {
96-
final List<String> resultUris = new LinkedList<>();
112+
final List<String> resultUris = new ArrayList<>();
97113

98114
final String uriWithQueryString = args[0].toString();
99115
final int queryStringIndex = uriWithQueryString.indexOf('?');
@@ -127,45 +143,53 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro
127143
queryStringMap.get(KEY_CONTENT_TYPE).equals(VALUE_CONTENT_TYPE_DOCUMENT_XML));
128144

129145
try (final Collection collection = context.getBroker().openCollection(uri, Lock.LockMode.READ_LOCK)) {
130-
if (binaryUrisIncluded || xmlUrisIncluded) {
131-
final Iterator<DocumentImpl> documentIterator = collection.iterator(context.getBroker());
132-
while (documentIterator.hasNext()) {
133-
final DocumentImpl document = documentIterator.next();
134-
if ((xmlUrisIncluded && !(document instanceof BinaryDocument)) ||
135-
(binaryUrisIncluded && document instanceof BinaryDocument)) {
136-
resultUris.add(document.getURI().toString());
146+
if (collection != null) {
147+
if (binaryUrisIncluded || xmlUrisIncluded) {
148+
final Iterator<DocumentImpl> documentIterator = collection.iterator(context.getBroker());
149+
while (documentIterator.hasNext()) {
150+
final DocumentImpl document = documentIterator.next();
151+
if ((xmlUrisIncluded && !(document instanceof BinaryDocument)) ||
152+
(binaryUrisIncluded && document instanceof BinaryDocument)) {
153+
resultUris.add(document.getURI().toString());
154+
}
137155
}
138156
}
139-
}
140157

141-
if (subcollectionUrisIncluded) {
142-
final Iterator<XmldbURI> collectionsIterator = collection.collectionIterator(context.getBroker());
143-
while (collectionsIterator.hasNext()) {
144-
resultUris.add(uri.append(collectionsIterator.next()).toString());
158+
if (subcollectionUrisIncluded) {
159+
final Iterator<XmldbURI> collectionsIterator = collection.collectionIterator(context.getBroker());
160+
while (collectionsIterator.hasNext()) {
161+
resultUris.add(uri.append(collectionsIterator.next()).toString());
162+
}
145163
}
164+
} else {
165+
throw new XPathException(this, ErrorCodes.FODC0002, String.format("Collection \"%s\" not found.", uri));
146166
}
147167
} catch (final LockException | PermissionDeniedException e) {
148168
throw new XPathException(this, ErrorCodes.FODC0002, e);
149169
}
150170

151171
if (queryStringMap.containsKey(KEY_MATCH) && queryStringMap.get(KEY_MATCH).length() > 0) {
152-
final Pattern pattern = Pattern.compile(queryStringMap.get(KEY_MATCH));
172+
final Pattern pattern = PatternFactory.getInstance().getPattern(queryStringMap.get(KEY_MATCH));
153173
final List<String> matchedResultUris = resultUris.stream().filter(resultUri -> pattern.matcher(resultUri).find()).collect(Collectors.toList());
154174
if (matchedResultUris.isEmpty()) {
155175
result = Sequence.EMPTY_SEQUENCE;
156176
} else {
157177
result = new ValueSequence();
158178
for (String resultUri : matchedResultUris) {
159-
result.add(new StringValue(resultUri));
179+
result.add(new AnyURIValue(resultUri));
160180
}
161181
}
162182
} else {
163183
result = new ValueSequence();
164184
for (String resultUri : resultUris) {
165-
result.add(new StringValue(resultUri));
185+
result.add(new AnyURIValue(resultUri));
166186
}
167187
}
168-
context.getCachedUriCollectionResults().put(uriWithoutStableQueryString, result);
188+
189+
// only store the result if they were not previously stored - otherwise we loose stability!
190+
if (!context.getCachedUriCollectionResults().containsKey(uriWithoutStableQueryString)) {
191+
context.getCachedUriCollectionResults().put(uriWithoutStableQueryString, result);
192+
}
169193
}
170194
}
171195

exist-core/src/test/xquery/xquery3/fnUriCollection.xqm

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,10 @@ function fnuc:not-stable() {
124124
let $a := xmldb:store("/db/test-collection", "test.xml", document { <container><a/><b/></container>})
125125
return $c2
126126
};
127+
128+
declare
129+
%test:assertError("FODC0002")
130+
function fnuc:non-existent-resource() {
131+
fn:uri-collection("thisfileshouldnotexists")
132+
};
133+

0 commit comments

Comments
 (0)