Skip to content

Commit 3bb0216

Browse files
committed
[feature] Implement 'declare default decimal-format' and 'declare decimal-format' prolog options in XQuery
1 parent f5af200 commit 3bb0216

5 files changed

Lines changed: 200 additions & 3 deletions

File tree

exist-core/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@
10731073
<include>src/main/java/org/exist/xquery/CombiningExpression.java</include>
10741074
<include>src/test/java/org/exist/xquery/ConstructedNodesRecoveryTest.java</include>
10751075
<include>src/main/java/org/exist/xquery/Context.java</include>
1076+
<include>src/main/java/org/exist/xquery/DecimalFormat.java</include>
10761077
<include>src/main/java/org/exist/xquery/DeferredFunctionCall.java</include>
10771078
<include>src/main/java/org/exist/xquery/DynamicCardinalityCheck.java</include>
10781079
<include>src/main/java/org/exist/xquery/DynamicTypeCheck.java</include>
@@ -1256,6 +1257,7 @@
12561257
<include>src/main/java/org/exist/xquery/functions/xmldb/XMLDBStore.java</include>
12571258
<include>src/main/java/org/exist/xquery/functions/xmldb/XMLDBXUpdate.java</include>
12581259
<include>src/test/java/org/exist/xquery/functions/xquery3/TryCatchTest.java</include>
1260+
<include>src/main/antlr/org/exist/xquery/parser/XQuery.g</include>
12591261
<include>src/main/antlr/org/exist/xquery/parser/XQueryTree.g</include>
12601262
<include>src/main/java/org/exist/xquery/pragmas/Optimize.java</include>
12611263
<include>src/test/java/org/exist/xquery/update/AbstractUpdateTest.java</include>
@@ -1738,6 +1740,7 @@
17381740
<exclude>src/main/java/org/exist/xquery/CombiningExpression.java</exclude>
17391741
<exclude>src/test/java/org/exist/xquery/ConstructedNodesRecoveryTest.java</exclude>
17401742
<exclude>src/main/java/org/exist/xquery/Context.java</exclude>
1743+
<exclude>src/main/java/org/exist/xquery/DecimalFormat.java</exclude>
17411744
<exclude>src/main/java/org/exist/xquery/DeferredFunctionCall.java</exclude>
17421745
<exclude>src/main/java/org/exist/xquery/DynamicCardinalityCheck.java</exclude>
17431746
<exclude>src/main/java/org/exist/xquery/DynamicTypeCheck.java</exclude>
@@ -1947,6 +1950,7 @@
19471950
<exclude>src/main/java/org/exist/xquery/functions/xmldb/XMLDBXUpdate.java</exclude>
19481951
<exclude>src/test/java/org/exist/xquery/functions/xquery3/SerializeTest.java</exclude>
19491952
<exclude>src/test/java/org/exist/xquery/functions/xquery3/TryCatchTest.java</exclude>
1953+
<exclude>src/main/antlr/org/exist/xquery/parser/XQuery.g</exclude>
19501954
<exclude>src/main/antlr/org/exist/xquery/parser/XQueryTree.g</exclude>
19511955
<exclude>src/main/java/org/exist/xquery/pragmas/Optimize.java</exclude>
19521956
<exclude>src/main/java/org/exist/xquery/pragmas/TimePragma.java</exclude>

exist-core/src/main/antlr/org/exist/xquery/parser/XQuery.g

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
* admin@evolvedbinary.com
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
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; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -143,6 +167,8 @@ imaginaryTokenDefinitions
143167
NAMESPACE_DECL
144168
DEF_NAMESPACE_DECL
145169
DEF_COLLATION_DECL
170+
DECIMAL_FORMAT_DECL
171+
DEFAULT_DECIMAL_FORMAT
146172
DEF_FUNCTION_NS_DECL
147173
CONTEXT_ITEM_DECL
148174
ANNOT_DECL
@@ -244,7 +270,7 @@ prolog throws XPathException
244270
(
245271
importDecl
246272
|
247-
( "declare" ( "default" | "boundary-space" | "ordering" | "construction" | "base-uri" | "copy-namespaces" | "namespace" ) ) =>
273+
( "declare" ( "default" | "boundary-space" | "ordering" | "construction" | "base-uri" | "copy-namespaces" | "namespace" | "decimal-format" ) ) =>
248274
s:setter
249275
{
250276
if(!inSetters)
@@ -283,10 +309,44 @@ versionDecl throws XPathException
283309
{ #versionDecl = #(#[VERSION_DECL, v.getText()], enc); }
284310
;
285311
312+
dfPropertyName
313+
:
314+
"decimal-separator"
315+
| "grouping-separator"
316+
| "infinity"
317+
| "minus-sign"
318+
| "NaN"
319+
| "percent"
320+
| "per-mille"
321+
| "zero-digit"
322+
| "digit"
323+
| "pattern-separator"
324+
| "exponent-separator"
325+
;
326+
327+
decimalFormatDecl
328+
{ String dfName = null; }
329+
:
330+
"declare"!
331+
(
332+
"default" "decimal-format"
333+
( dfPropertyName EQ! STRING_LITERAL )*
334+
{
335+
## = #( #[DECIMAL_FORMAT_DECL, "DECIMAL_FORMAT_DECL"], #[DEFAULT_DECIMAL_FORMAT, "DEFAULT_DECIMAL_FORMAT"], ## );
336+
}
337+
|
338+
"decimal-format" eqName
339+
( dfPropertyName EQ! STRING_LITERAL )*
340+
{
341+
## = #( #[DECIMAL_FORMAT_DECL, "DECIMAL_FORMAT_DECL"], ## );
342+
}
343+
)
344+
;
345+
286346
setter
287347
:
288348
(
289-
( "declare" "default" ) =>
349+
( "declare" "default" ( "collation" | "element" | "function" | "order" ) ) =>
290350
"declare"! "default"!
291351
(
292352
"collation"! defc:STRING_LITERAL
@@ -318,6 +378,8 @@ setter
318378
|
319379
( "declare" "namespace" ) =>
320380
namespaceDecl
381+
| ( "declare" ( "default" )? "decimal-format" ) =>
382+
decimalFormatDecl
321383
)
322384
;
323385

exist-core/src/main/antlr/org/exist/xquery/parser/XQueryTree.g

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,56 @@ throws PermissionDeniedException, EXistException, XPathException
497497
}
498498
)
499499
|
500+
#(
501+
DECIMAL_FORMAT_DECL
502+
{
503+
final XQueryAST root = (XQueryAST) _t; // points to DECIMAL_FORMAT_DECL
504+
// first sibling is either DEFAULT_DECIMAL_FORMAT (default) or EQNAME (named)
505+
final XQueryAST dfName = (XQueryAST) root.getNextSibling();
506+
507+
// position current at the first property name for the decimal format
508+
XQueryAST current = (XQueryAST) dfName.getNextSibling();
509+
if ("default".equals(dfName.getText())) {
510+
current = (XQueryAST) current.getNextSibling();
511+
}
512+
513+
final Map<String, String> dfProperties = new HashMap<>();
514+
515+
while (current != null) {
516+
final XQueryAST pname = current;
517+
final XQueryAST pval = (XQueryAST) current.getNextSibling();
518+
519+
if (pval == null) {
520+
break;
521+
}
522+
523+
final String pn = pname.getText();
524+
String pv = pval.getText();
525+
if (pv.length() >= 2 && (pv.startsWith("\"") || pv.startsWith("'"))) {
526+
pv = pv.substring(1, pv.length() - 1);
527+
}
528+
dfProperties.put(pn, pv);
529+
530+
current = (XQueryAST) pval.getNextSibling();
531+
}
532+
533+
final QName qnDfName;
534+
if ("default".equals(dfName.getText())) {
535+
qnDfName = XQueryContext.UNNAMED_DECIMAL_FORMAT;
536+
} else {
537+
try {
538+
qnDfName = QName.parse(staticContext, dfName.getText(), null);
539+
} catch (final IllegalQNameException iqe) {
540+
throw new XPathException(dfName.getLine(), dfName.getColumn(), ErrorCodes.XPST0081, "No namespace defined for prefix " + dfName.getText());
541+
}
542+
}
543+
544+
final DecimalFormat df = DecimalFormat.fromProperties(dfProperties);
545+
staticContext.setStaticDecimalFormat(qnDfName, df);
546+
context.setStaticDecimalFormat(qnDfName, df);
547+
}
548+
)
549+
|
500550
#(
501551
qname:GLOBAL_VAR
502552
{

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

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,28 @@
11
/*
2+
* Elemental
3+
* Copyright (C) 2024, Evolved Binary Ltd
4+
*
5+
* admin@evolvedbinary.com
6+
* https://www.evolvedbinary.com | https://www.elemental.xyz
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; version 2.1.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
* NOTE: Parts of this file contain code from 'The eXist-db Authors'.
22+
* The original license header is included below.
23+
*
24+
* =====================================================================
25+
*
226
* eXist-db Open Source Native XML Database
327
* Copyright (C) 2001 The eXist-db Authors
428
*
@@ -21,6 +45,8 @@
2145
*/
2246
package org.exist.xquery;
2347

48+
import java.util.Map;
49+
2450
/**
2551
* Data class for a Decimal Format.
2652
*
@@ -79,4 +105,59 @@ public DecimalFormat(final int decimalSeparator, final int exponentSeparator, fi
79105
this.NaN = NaN;
80106
this.minusSign = minusSign;
81107
}
108+
109+
public static DecimalFormat fromProperties(final Map<String, String> properties) {
110+
int decimalSeparator = UNNAMED.decimalSeparator;
111+
int exponentSeparator = UNNAMED.exponentSeparator;
112+
int groupingSeparator = UNNAMED.groupingSeparator;
113+
int percent = UNNAMED.percent;
114+
int perMille = UNNAMED.perMille;
115+
int zeroDigit = UNNAMED.zeroDigit;
116+
int digit = UNNAMED.digit;
117+
int patternSeparator = UNNAMED.patternSeparator;
118+
String infinity = UNNAMED.infinity;
119+
String NaN = UNNAMED.NaN;
120+
int minusSign = UNNAMED.minusSign;
121+
122+
for (final Map.Entry<String, String> property : properties.entrySet()) {
123+
final String value = property.getValue();
124+
switch (property.getKey()) {
125+
case "decimal-separator":
126+
decimalSeparator = value.charAt(0);
127+
break;
128+
case "exponent-separator":
129+
exponentSeparator = value.charAt(0);
130+
break;
131+
case "grouping-separator":
132+
groupingSeparator = value.charAt(0);
133+
break;
134+
case "percent":
135+
percent = value.charAt(0);
136+
break;
137+
case "per-mille":
138+
perMille = value.charAt(0);
139+
break;
140+
case "zero-digit":
141+
zeroDigit = value.charAt(0);
142+
break;
143+
case "digit":
144+
digit = value.charAt(0);
145+
break;
146+
case "pattern-separator":
147+
patternSeparator = value.charAt(0);
148+
break;
149+
case "infinity":
150+
infinity = value;
151+
break;
152+
case "NaN":
153+
NaN = value;
154+
break;
155+
case "minus-sign":
156+
minusSign = value.charAt(0);
157+
break;
158+
}
159+
}
160+
161+
return new DecimalFormat(decimalSeparator, exponentSeparator, groupingSeparator, percent, perMille, zeroDigit, digit, patternSeparator, infinity, NaN, minusSign);
162+
}
82163
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ public class XQueryContext implements BinaryValueManager, Context {
444444
*/
445445
@Nullable
446446
private HttpContext httpContext = null;
447-
private static final QName UNNAMED_DECIMAL_FORMAT = new QName("__UNNAMED__", Namespaces.XPATH_FUNCTIONS_NS);
447+
public static final QName UNNAMED_DECIMAL_FORMAT = new QName("__UNNAMED__", Namespaces.XPATH_FUNCTIONS_NS);
448448

449449
private final Map<QName, DecimalFormat> staticDecimalFormats = HashMap(Tuple(UNNAMED_DECIMAL_FORMAT, DecimalFormat.UNNAMED));
450450

0 commit comments

Comments
 (0)