Skip to content

Commit 5818c56

Browse files
authored
Merge pull request #5077 from evolvedbinary/6.x.x/feat/time-pragma
[6.x.x] New exist:time XQuery Pragma
2 parents 5fbc4de + bd13f59 commit 5818c56

File tree

14 files changed

+875
-413
lines changed

14 files changed

+875
-413
lines changed

exist-core/pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,7 @@
712712
<exclude>src/test/java/org/exist/xquery/functions/session/AttributeTest.java</exclude>
713713
<exclude>src/test/java/org/exist/xquery/functions/xmldb/XMLDBAuthenticateTest.java</exclude>
714714
<exclude>src/main/java/org/exist/xquery/functions/util/Eval.java</exclude>
715+
<exclude>src/main/java/org/exist/xquery/pragmas/TimePragma.java</exclude>
715716
<exclude>src/test/java/org/exist/xquery/util/URIUtilsTest.java</exclude>
716717
<exclude>src/main/java/org/exist/xquery/value/ArrayListValueSequence.java</exclude>
717718
<exclude>src/test/java/org/exist/xquery/value/BifurcanMapTest.java</exclude>
@@ -862,6 +863,7 @@ The original license statement is also included below.]]></preamble>
862863
<include>src/test/java/org/exist/xquery/functions/session/AttributeTest.java</include>
863864
<include>src/test/java/org/exist/xquery/functions/xmldb/XMLDBAuthenticateTest.java</include>
864865
<include>src/main/java/org/exist/xquery/functions/util/Eval.java</include>
866+
<include>src/main/java/org/exist/xquery/pragmas/TimePragma.java</include>
865867
<include>src/test/java/org/exist/xquery/util/URIUtilsTest.java</include>
866868
<include>src/main/java/org/exist/xquery/value/ArrayListValueSequence.java</include>
867869
<include>src/test/java/org/exist/xquery/value/BifurcanMapTest.java</include>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* eXist-db Open Source Native XML Database
3+
* Copyright (C) 2001 The eXist-db Authors
4+
*
5+
6+
* http://www.exist-db.org
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; either
11+
* version 2.1 of the License, or (at your option) any later version.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*/
22+
package org.exist.xquery;
23+
24+
import org.exist.dom.QName;
25+
import org.exist.xquery.util.ExpressionDumper;
26+
import org.exist.xquery.value.Item;
27+
import org.exist.xquery.value.Sequence;
28+
29+
import javax.annotation.Nullable;
30+
31+
/**
32+
* Base class for implementing an XQuery Pragma expression.
33+
*
34+
* @author <a href="mailto:[email protected]">Adam Retter</a>
35+
*/
36+
public abstract class AbstractPragma implements Pragma {
37+
private final QName name;
38+
private @Nullable final String contents;
39+
private @Nullable final Expression expression;
40+
41+
public AbstractPragma(@Nullable final Expression expression, final QName name, @Nullable final String contents) {
42+
this.expression = expression;
43+
this.name = name;
44+
this.contents = contents;
45+
}
46+
47+
@Override
48+
public QName getName() {
49+
return name;
50+
}
51+
52+
public @Nullable Expression getExpression() {
53+
return expression;
54+
}
55+
56+
@Override
57+
public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException {
58+
// no-op by default
59+
}
60+
61+
@Override
62+
public void before(final XQueryContext context, @Nullable final Expression expression, final Sequence contextSequence) throws XPathException {
63+
// no-op by default
64+
}
65+
66+
@Override
67+
public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException {
68+
// no-op by default
69+
return null;
70+
}
71+
72+
@Override
73+
public void after(final XQueryContext context, @Nullable final Expression expression) throws XPathException {
74+
// no-op by default
75+
}
76+
77+
protected @Nullable String getContents() {
78+
return contents;
79+
}
80+
81+
@Override
82+
public void dump(final ExpressionDumper dumper) {
83+
dumper.display("(# " + getName().getStringValue());
84+
if (getContents() != null) {
85+
dumper.display(' ').display(getContents());
86+
}
87+
}
88+
89+
@Override
90+
public void resetState(final boolean postOptimization) {
91+
//no-op by default
92+
}
93+
94+
@Override
95+
public String toString() {
96+
return "(# " + name + ' ' + contents + "#)";
97+
}
98+
}

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

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,23 @@
3333
* Implements an XQuery extension expression. An extension expression starts with
3434
* a list of pragmas, followed by an expression enclosed in curly braces. For evaluation
3535
* details check {{@link #eval(Sequence, Item)}.
36-
*
37-
* @author wolf
3836
*
37+
* @author wolf
3938
*/
4039
public class ExtensionExpression extends AbstractExpression {
4140

4241
private Expression innerExpression;
43-
private List<Pragma> pragmas = new ArrayList<>(3);
42+
private final List<Pragma> pragmas = new ArrayList<>(3);
4443

45-
public ExtensionExpression(XQueryContext context) {
44+
public ExtensionExpression(final XQueryContext context) {
4645
super(context);
4746
}
4847

49-
public void setExpression(Expression inner) {
48+
public void setExpression(final Expression inner) {
5049
this.innerExpression = inner;
5150
}
5251

53-
public void addPragma(Pragma pragma) {
52+
public void addPragma(final Pragma pragma) {
5453
pragmas.add(pragma);
5554
}
5655

@@ -62,19 +61,20 @@ public void addPragma(Pragma pragma) {
6261
* will be thrown. If all pragmas return null, we call eval on the original expression and return
6362
* that.
6463
*/
65-
public Sequence eval(Sequence contextSequence, Item contextItem)
66-
throws XPathException {
64+
@Override
65+
public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException {
6766
callBefore(contextSequence);
6867
Sequence result = null;
6968
for (final Pragma pragma : pragmas) {
70-
Sequence temp = pragma.eval(contextSequence, contextItem);
69+
final Sequence temp = pragma.eval(contextSequence, contextItem);
7170
if (temp != null) {
7271
result = temp;
7372
break;
7473
}
7574
}
76-
if (result == null)
77-
{result = innerExpression.eval(contextSequence, contextItem);}
75+
if (result == null) {
76+
result = innerExpression.eval(contextSequence, contextItem);
77+
}
7878
callAfter();
7979
return result;
8080
}
@@ -85,7 +85,7 @@ private void callAfter() throws XPathException {
8585
}
8686
}
8787

88-
private void callBefore(Sequence contextSequence) throws XPathException {
88+
private void callBefore(final Sequence contextSequence) throws XPathException {
8989
for (final Pragma pragma : pragmas) {
9090
pragma.before(context, innerExpression, contextSequence);
9191
}
@@ -95,31 +95,27 @@ public int returnsType() {
9595
return innerExpression.returnsType();
9696
}
9797

98-
public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
98+
public void analyze(final AnalyzeContextInfo contextInfo) throws XPathException {
9999
final AnalyzeContextInfo newContext = new AnalyzeContextInfo(contextInfo);
100100
for (final Pragma pragma : pragmas) {
101101
pragma.analyze(newContext);
102102
}
103103
innerExpression.analyze(newContext);
104104
}
105105

106-
public void dump(ExpressionDumper dumper) {
106+
public void dump(final ExpressionDumper dumper) {
107107
for (final Pragma pragma : pragmas) {
108-
dumper.display("(# " + pragma.getQName().getStringValue(), line);
109-
if (pragma.getContents() != null)
110-
{dumper.display(' ').display(pragma.getContents());}
111-
dumper.display("#)").nl();
108+
pragma.dump(dumper);
109+
dumper.nl();
112110
}
113111
dumper.display('{');
114112
dumper.startIndent();
115113
innerExpression.dump(dumper);
116114
dumper.endIndent();
117-
dumper.nl().display('}').nl();
115+
dumper.nl().display("}", line).nl();
118116
}
119117

120-
/* (non-Javadoc)
121-
* @see org.exist.xquery.AbstractExpression#getDependencies()
122-
*/
118+
@Override
123119
public int getDependencies() {
124120
return innerExpression.getDependencies();
125121
}
@@ -129,31 +125,33 @@ public Cardinality getCardinality() {
129125
return innerExpression.getCardinality();
130126
}
131127

132-
public void setContextDocSet(DocumentSet contextSet) {
128+
@Override
129+
public void setContextDocSet(final DocumentSet contextSet) {
133130
super.setContextDocSet(contextSet);
134131
innerExpression.setContextDocSet(contextSet);
135132
}
136133

137-
public void setPrimaryAxis(int axis) {
134+
@Override
135+
public void setPrimaryAxis(final int axis) {
138136
innerExpression.setPrimaryAxis(axis);
139137
}
140138

139+
@Override
141140
public int getPrimaryAxis() {
142141
return innerExpression.getPrimaryAxis();
143142
}
144143

145-
/* (non-Javadoc)
146-
* @see org.exist.xquery.AbstractExpression#resetState()
147-
*/
148-
public void resetState(boolean postOptimization) {
144+
@Override
145+
public void resetState(final boolean postOptimization) {
149146
super.resetState(postOptimization);
150147
innerExpression.resetState(postOptimization);
151148
for (final Pragma pragma : pragmas) {
152149
pragma.resetState(postOptimization);
153150
}
154151
}
155152

156-
public void accept(ExpressionVisitor visitor) {
153+
@Override
154+
public void accept(final ExpressionVisitor visitor) {
157155
visitor.visit(innerExpression);
158156
}
159157
}

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,12 @@
2121
*/
2222
package org.exist.xquery;
2323

24-
import org.exist.dom.QName;
2524
import org.exist.storage.DBBroker;
2625
import org.exist.xquery.functions.array.ArrayConstructor;
2726
import org.exist.xquery.pragmas.Optimize;
2827
import org.apache.logging.log4j.LogManager;
2928
import org.apache.logging.log4j.Logger;
3029
import org.exist.xquery.util.ExpressionDumper;
31-
import org.exist.xquery.value.AtomicValue;
32-
import org.exist.xquery.value.Type;
3330

3431
import javax.annotation.Nullable;
3532
import java.util.*;
@@ -82,15 +79,15 @@ public void visitLocationStep(final LocationStep locationStep) {
8279

8380
// check query rewriters if they want to rewrite the location step
8481
Pragma optimizePragma = null;
85-
for (QueryRewriter rewriter : rewriters) {
82+
for (final QueryRewriter rewriter : rewriters) {
8683
try {
8784
optimizePragma = rewriter.rewriteLocationStep(locationStep);
8885
if (optimizePragma != null) {
8986
// expression was rewritten: return
9087
hasOptimized = true;
9188
break;
9289
}
93-
} catch (XPathException e) {
90+
} catch (final XPathException e) {
9491
LOG.warn("Exception called while rewriting location step: {}", e.getMessage(), e);
9592
}
9693
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.exist.Namespaces;
2929
import org.exist.dom.QName;
3030

31+
import javax.annotation.Nullable;
32+
3133
/**
3234
* Represents an XQuery option declared via "declare option".
3335
*
@@ -89,9 +91,9 @@ public static String[] tokenize(final String contents) {
8991
return items;
9092
}
9193

92-
public static String[] parseKeyValuePair(final String s) {
94+
public static @Nullable String[] parseKeyValuePair(final String s) {
9395
final Matcher matcher = pattern.matcher(s);
94-
if(matcher.matches()) {
96+
if (matcher.matches()) {
9597
String value = matcher.group(2);
9698
if(value.charAt(0) == '\'' || value.charAt(0) == '"') {
9799
value = value.substring(1, value.length() - 1);

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

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,57 +22,30 @@
2222
package org.exist.xquery;
2323

2424
import org.exist.dom.QName;
25+
import org.exist.xquery.util.ExpressionDumper;
2526
import org.exist.xquery.value.Item;
2627
import org.exist.xquery.value.Sequence;
2728

28-
public abstract class Pragma {
29+
import javax.annotation.Nullable;
2930

30-
private QName qname;
31-
private String contents;
32-
private Expression expression;
33-
34-
public Pragma(QName qname, String contents) throws XPathException {
35-
this(null, qname, contents);
36-
}
37-
38-
public Pragma(final Expression expression, QName qname, String contents) throws XPathException {
39-
this.expression = expression;
40-
this.qname = qname;
41-
this.contents = contents;
42-
}
31+
/**
32+
* Interface for implementing an XQuery Pragma expression.
33+
*
34+
* @author <a href="mailto:[email protected]">Adam Retter</a>
35+
*/
36+
public interface Pragma {
4337

44-
public Expression getExpression() {
45-
return expression;
46-
}
38+
QName getName();
4739

48-
public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
49-
}
40+
void analyze(AnalyzeContextInfo contextInfo) throws XPathException;
5041

51-
public Sequence eval(Sequence contextSequence, Item contextItem)
52-
throws XPathException {
53-
return null;
54-
}
55-
56-
public abstract void before(XQueryContext context, Sequence contextSequence) throws XPathException;
57-
58-
public abstract void before(XQueryContext context, final Expression expression, Sequence contextSequence) throws XPathException;
59-
60-
public abstract void after(XQueryContext context) throws XPathException;
61-
62-
public abstract void after(XQueryContext context, final Expression expression) throws XPathException;
42+
void before(XQueryContext context, @Nullable Expression expression, Sequence contextSequence) throws XPathException;
6343

64-
protected String getContents() {
65-
return contents;
66-
}
44+
Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException;
6745

68-
protected QName getQName() {
69-
return qname;
70-
}
46+
void after(XQueryContext context, @Nullable Expression expression) throws XPathException;
7147

72-
public void resetState(boolean postOptimization) {
73-
}
48+
void dump(final ExpressionDumper dumper);
7449

75-
public String toString() {
76-
return "(# " + qname + ' ' + contents + "#)";
77-
}
78-
}
50+
void resetState(boolean postOptimization);
51+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3076,8 +3076,8 @@ public Pragma getPragma(final String name, String contents) throws XPathExceptio
30763076
} else if (Namespaces.EXIST_NS.equals(qname.getNamespaceURI())) {
30773077
contents = StringValue.trimWhitespace(contents);
30783078

3079-
if (TimerPragma.TIMER_PRAGMA.equals(qname)) {
3080-
return new TimerPragma(rootExpression, qname, contents);
3079+
if (TimePragma.TIME_PRAGMA_NAME.equals(qname) || TimePragma.DEPRECATED_TIMER_PRAGMA_NAME.equals(qname)) {
3080+
return new TimePragma(rootExpression, qname, contents);
30813081
}
30823082

30833083
if (Optimize.OPTIMIZE_PRAGMA.equals(qname)) {

0 commit comments

Comments
 (0)