• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

evolvedbinary / elemental / 982

29 Apr 2025 08:34PM UTC coverage: 56.409% (+0.007%) from 56.402%
982

push

circleci

adamretter
[feature] Improve README.md badges

28451 of 55847 branches covered (50.94%)

Branch coverage included in aggregate %.

77468 of 131924 relevant lines covered (58.72%)

0.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.78
/exist-core/src/main/java/org/exist/xquery/value/Type.java
1
/*
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
 * Use of this software is governed by the Business Source License 1.1
9
 * included in the LICENSE file and at www.mariadb.com/bsl11.
10
 *
11
 * Change Date: 2028-04-27
12
 *
13
 * On the date above, in accordance with the Business Source License, use
14
 * of this software will be governed by the Apache License, Version 2.0.
15
 *
16
 * Additional Use Grant: Production use of the Licensed Work for a permitted
17
 * purpose. A Permitted Purpose is any purpose other than a Competing Use.
18
 * A Competing Use means making the Software available to others in a commercial
19
 * product or service that: substitutes for the Software; substitutes for any
20
 * other product or service we offer using the Software that exists as of the
21
 * date we make the Software available; or offers the same or substantially
22
 * similar functionality as the Software.
23
 *
24
 * NOTE: Parts of this file contain code from 'The eXist-db Authors'.
25
 *       The original license header is included below.
26
 *
27
 * =====================================================================
28
 *
29
 * eXist-db Open Source Native XML Database
30
 * Copyright (C) 2001 The eXist-db Authors
31
 *
32
 * info@exist-db.org
33
 * http://www.exist-db.org
34
 *
35
 * This library is free software; you can redistribute it and/or
36
 * modify it under the terms of the GNU Lesser General Public
37
 * License as published by the Free Software Foundation; either
38
 * version 2.1 of the License, or (at your option) any later version.
39
 *
40
 * This library is distributed in the hope that it will be useful,
41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
43
 * Lesser General Public License for more details.
44
 *
45
 * You should have received a copy of the GNU Lesser General Public
46
 * License along with this library; if not, write to the Free Software
47
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
48
 */
49
package org.exist.xquery.value;
50

51
import it.unimi.dsi.fastutil.Hash;
52
import it.unimi.dsi.fastutil.ints.*;
53
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
54
import org.apache.logging.log4j.LogManager;
55
import org.apache.logging.log4j.Logger;
56
import org.exist.Namespaces;
57
import org.exist.dom.QName;
58
import org.exist.xquery.Expression;
59
import org.exist.xquery.XPathException;
60
import org.w3c.dom.Node;
61

62
import javax.annotation.Nullable;
63

64
/**
65
 * Defines all built-in types and their relations.
66
 *
67
 * @author <a href="mailto:wolfgang@exist-db.org">Wolfgang Meier</a>
68
 * @author <a href="mailto:adam@evolvedbinary.com">Adam Retter</a>
69
 */
70
public class Type {
×
71

72
    private final static Logger LOG = LogManager.getLogger(Type.class);
1✔
73

74
    // Tombstone value used for FastUtil Int maps
75
    private static final int NO_SUCH_VALUE = -99;
76

77
    public final static int ITEM = 1;
78

79
    public final static int ANY_TYPE = 2;
80

81
    public final static int ANY_SIMPLE_TYPE = 3;
82

83
    /* xs:anyAtomicType and its subtypes */
84
    public final static int ANY_ATOMIC_TYPE = 4;
85
    public final static int UNTYPED_ATOMIC = 5;
86
    public final static int DATE_TIME = 6;
87
    public final static int DATE_TIME_STAMP = 7;
88
    public final static int DATE = 8;
89
    public final static int TIME = 9;
90
    public final static int DURATION = 10;
91
    public final static int YEAR_MONTH_DURATION = 11;
92
    public final static int DAY_TIME_DURATION = 12;
93
    public final static int FLOAT = 13;
94
    public final static int DOUBLE = 14;
95
    public final static int DECIMAL = 15;
96
    public final static int INTEGER = 16;
97
    public final static int NON_POSITIVE_INTEGER = 17;
98
    public final static int NEGATIVE_INTEGER = 18;
99
    public final static int LONG = 19;
100
    public final static int INT = 20;
101
    public final static int SHORT = 21;
102
    public final static int BYTE = 22;
103
    public final static int NON_NEGATIVE_INTEGER = 23;
104
    public final static int UNSIGNED_LONG = 24;
105
    public final static int UNSIGNED_INT = 25;
106
    public final static int UNSIGNED_SHORT = 26;
107
    public final static int UNSIGNED_BYTE = 27;
108
    public final static int POSITIVE_INTEGER = 28;
109
    public final static int G_YEAR_MONTH = 29;
110
    public final static int G_YEAR = 30;
111
    public final static int G_MONTH_DAY = 31;
112
    public final static int G_DAY = 32;
113
    public final static int G_MONTH = 33;
114
    public final static int STRING = 34;
115
    public final static int NORMALIZED_STRING = 35;
116
    public final static int TOKEN = 36;
117
    public final static int LANGUAGE = 37;
118
    public final static int NMTOKEN = 38;
119
    public final static int NAME = 39;
120
    public final static int NCNAME = 40;
121
    public final static int ID = 41;
122
    public final static int IDREF = 42;
123
    public final static int ENTITY = 43;
124
    public final static int BOOLEAN = 44;
125
    public final static int BASE64_BINARY = 45;
126
    public final static int HEX_BINARY = 46;
127
    public final static int ANY_URI = 47;
128
    public final static int QNAME = 48;
129
    public final static int NOTATION = 49;
130

131
    /* list types */
132
    public final static int NMTOKENS = 50;
133
    public final static int IDREFS = 51;
134
    public final static int ENTITIES = 52;
135

136
    /* union types */
137
    public final static int NUMERIC = 53;
138
    public final static int ERROR = 54;
139

140
    /* complex types */
141
    public final static int UNTYPED = 55;
142

143
    /* nodes */
144
    public static final int NODE = 56;
145
    public final static int ATTRIBUTE = 57;
146
    public final static int COMMENT = 58;
147
    public final static int DOCUMENT = 59;
148
    public final static int ELEMENT = 60;
149
    public final static int NAMESPACE = 61;
150
    public final static int PROCESSING_INSTRUCTION = 62;
151
    public final static int TEXT = 63;
152

153
    /* functions */
154
    public final static int FUNCTION = 64;
155
    public final static int ARRAY_ITEM = 65;
156
    public final static int MAP_ITEM = 66;
157

158
    // NOTE(AR) the types below do NOT appear in the XDM 3.1 spec - https://www.w3.org/TR/xpath-datamodel-31
159
    public final static int CDATA_SECTION = 67;
160
    public final static int JAVA_OBJECT = 68;
161
    public final static int EMPTY_SEQUENCE = 69;  // NOTE(AR) this types does appear in the XQ 3.1 spec - https://www.w3.org/TR/xquery-31/#id-sequencetype-syntax
162

163
    private final static int[] superTypes = new int[69];
1✔
164
    private final static Int2ObjectOpenHashMap<String[]> typeNames = new Int2ObjectOpenHashMap<>(69, Hash.FAST_LOAD_FACTOR);
1✔
165
    private final static Object2IntOpenHashMap<String> typeCodes = new Object2IntOpenHashMap<>(78, Hash.FAST_LOAD_FACTOR);
1✔
166
    static {
167
        typeCodes.defaultReturnValue(NO_SUCH_VALUE);
1✔
168
    }
169
    private final static Int2ObjectMap<IntArraySet> unionTypes = new Int2ObjectArrayMap<>(2);
1✔
170
    private final static Int2IntOpenHashMap primitiveTypes = new Int2IntOpenHashMap(45, Hash.FAST_LOAD_FACTOR);
1✔
171
    static {
172
        primitiveTypes.defaultReturnValue(NO_SUCH_VALUE);
1✔
173
    }
174

175
    static {
176
        // ANY types
177
        defineSubType(ANY_TYPE, ANY_SIMPLE_TYPE);
1✔
178
        defineSubType(ANY_TYPE, UNTYPED);
1✔
179

180
        // ANY_SIMPLE types
181
        defineSubType(ANY_SIMPLE_TYPE, ANY_ATOMIC_TYPE);
1✔
182
        defineSubType(ANY_SIMPLE_TYPE, IDREFS);
1✔
183
        defineSubType(ANY_SIMPLE_TYPE, NMTOKENS);
1✔
184
        defineSubType(ANY_SIMPLE_TYPE, ENTITIES);
1✔
185
        defineSubType(ANY_SIMPLE_TYPE, NUMERIC);
1✔
186
        defineSubType(ANY_SIMPLE_TYPE, ERROR);
1✔
187

188
        // ITEM sub-types
189
        defineSubType(ITEM, ANY_ATOMIC_TYPE);
1✔
190
        defineSubType(ITEM, FUNCTION);
1✔
191
        defineSubType(ITEM, NODE);
1✔
192

193
        // ATOMIC sub-types
194
        defineSubType(ANY_ATOMIC_TYPE, ANY_URI);
1✔
195
        defineSubType(ANY_ATOMIC_TYPE, BASE64_BINARY);
1✔
196
        defineSubType(ANY_ATOMIC_TYPE, BOOLEAN);
1✔
197
        defineSubType(ANY_ATOMIC_TYPE, DATE);
1✔
198
        defineSubType(ANY_ATOMIC_TYPE, DATE_TIME);
1✔
199
        defineSubType(ANY_ATOMIC_TYPE, DECIMAL);
1✔
200
        defineSubType(ANY_ATOMIC_TYPE, DOUBLE);
1✔
201
        defineSubType(ANY_ATOMIC_TYPE, DURATION);
1✔
202
        defineSubType(ANY_ATOMIC_TYPE, FLOAT);
1✔
203
        defineSubType(ANY_ATOMIC_TYPE, G_DAY);
1✔
204
        defineSubType(ANY_ATOMIC_TYPE, G_MONTH);
1✔
205
        defineSubType(ANY_ATOMIC_TYPE, G_MONTH_DAY);
1✔
206
        defineSubType(ANY_ATOMIC_TYPE, G_YEAR);
1✔
207
        defineSubType(ANY_ATOMIC_TYPE, G_YEAR_MONTH);
1✔
208
        defineSubType(ANY_ATOMIC_TYPE, HEX_BINARY);
1✔
209
        defineSubType(ANY_ATOMIC_TYPE, JAVA_OBJECT);
1✔
210
        defineSubType(ANY_ATOMIC_TYPE, NOTATION);
1✔
211
        defineSubType(ANY_ATOMIC_TYPE, QNAME);
1✔
212
        defineSubType(ANY_ATOMIC_TYPE, STRING);
1✔
213
        defineSubType(ANY_ATOMIC_TYPE, TIME);
1✔
214
        defineSubType(ANY_ATOMIC_TYPE, UNTYPED_ATOMIC);
1✔
215

216
        // DATE_TIME sub-types
217
        defineSubType(DATE_TIME, DATE_TIME_STAMP);
1✔
218

219
        // DURATION sub-types
220
        defineSubType(DURATION, DAY_TIME_DURATION);
1✔
221
        defineSubType(DURATION, YEAR_MONTH_DURATION);
1✔
222

223
        // DECIMAL sub-types
224
        defineSubType(DECIMAL, INTEGER);
1✔
225

226
        // INTEGER sub-types
227
        defineSubType(INTEGER, LONG);
1✔
228
        defineSubType(INTEGER, NON_NEGATIVE_INTEGER);
1✔
229
        defineSubType(INTEGER, NON_POSITIVE_INTEGER);
1✔
230

231
        // LONG sub-types
232
        defineSubType(LONG, INT);
1✔
233

234
        // INT sub-types
235
        defineSubType(INT, SHORT);
1✔
236

237
        // SHORT sub-types
238
        defineSubType(SHORT, BYTE);
1✔
239

240
        // NON_NEGATIVE_INTEGER sub-types
241
        defineSubType(NON_NEGATIVE_INTEGER, POSITIVE_INTEGER);
1✔
242
        defineSubType(NON_NEGATIVE_INTEGER, UNSIGNED_LONG);
1✔
243

244
        // UNSIGNED_LONG sub-types
245
        defineSubType(UNSIGNED_LONG, UNSIGNED_INT);
1✔
246

247
        // UNSIGNED_INT sub-types
248
        defineSubType(UNSIGNED_INT, UNSIGNED_SHORT);
1✔
249

250
        // UNSIGNED_SHORT sub-types
251
        defineSubType(UNSIGNED_SHORT, UNSIGNED_BYTE);
1✔
252

253
        // NON_POSITIVE_INTEGER sub-types
254
        defineSubType(NON_POSITIVE_INTEGER, NEGATIVE_INTEGER);
1✔
255

256
        // STRING sub-types
257
        defineSubType(STRING, NORMALIZED_STRING);
1✔
258

259
        // NORMALIZED_STRING sub-types
260
        defineSubType(NORMALIZED_STRING, TOKEN);
1✔
261

262
        // TOKEN sub-types
263
        defineSubType(TOKEN, LANGUAGE);
1✔
264
        defineSubType(TOKEN, NAME);
1✔
265
        defineSubType(TOKEN, NMTOKEN);
1✔
266

267
        // NAME sub-types
268
        defineSubType(NAME, NCNAME);
1✔
269

270
        // NCNAME sub-types
271
        defineSubType(NCNAME, ENTITY);
1✔
272
        defineSubType(NCNAME, ID);
1✔
273
        defineSubType(NCNAME, IDREF);
1✔
274

275
        // FUNCTION_REFERENCE sub-types
276
        defineSubType(FUNCTION, MAP_ITEM);
1✔
277
        defineSubType(FUNCTION, ARRAY_ITEM);
1✔
278

279
        // NODE types
280
        defineSubType(NODE, ATTRIBUTE);
1✔
281
        defineSubType(NODE, CDATA_SECTION);
1✔
282
        defineSubType(NODE, COMMENT);
1✔
283
        defineSubType(NODE, DOCUMENT);
1✔
284
        defineSubType(NODE, ELEMENT);
1✔
285
        defineSubType(NODE, NAMESPACE);
1✔
286
        defineSubType(NODE, PROCESSING_INSTRUCTION);
1✔
287
        defineSubType(NODE, TEXT);
1✔
288
    }
289

290
    static {
291
        defineBuiltInType(ITEM, "item()");
1✔
292
        defineBuiltInType(ANY_TYPE, "xs:anyType");
1✔
293
        defineBuiltInType(ANY_SIMPLE_TYPE, "xs:anySimpleType");
1✔
294
        defineBuiltInType(ANY_ATOMIC_TYPE, "xs:anyAtomicType", "xdt:anyAtomicType");                // keep `xdt:anyAtomicType` for backward compatibility
1✔
295
        defineBuiltInType(UNTYPED_ATOMIC, "xs:untypedAtomic", "xdt:untypedAtomic");                 // keep `xdt:untypedAtomic` for backward compatibility
1✔
296
        defineBuiltInType(DATE_TIME, "xs:dateTime");
1✔
297
        defineBuiltInType(DATE_TIME_STAMP, "xs:dateTimeStamp");
1✔
298
        defineBuiltInType(DATE, "xs:date");
1✔
299
        defineBuiltInType(TIME, "xs:time");
1✔
300
        defineBuiltInType(DURATION, "xs:duration");
1✔
301
        defineBuiltInType(YEAR_MONTH_DURATION, "xs:yearMonthDuration", "xdt:yearMonthDuration");    // keep `xdt:yearMonthDuration` for backward compatibility
1✔
302
        defineBuiltInType(DAY_TIME_DURATION, "xs:dayTimeDuration", "xdt:dayTimeDuration");          // keep `xdt:dayTimeDuration` for backward compatibility
1✔
303
        defineBuiltInType(FLOAT, "xs:float");
1✔
304
        defineBuiltInType(DOUBLE, "xs:double");
1✔
305
        defineBuiltInType(DECIMAL, "xs:decimal");
1✔
306
        defineBuiltInType(INTEGER, "xs:integer");
1✔
307
        defineBuiltInType(NON_POSITIVE_INTEGER, "xs:nonPositiveInteger");
1✔
308
        defineBuiltInType(NEGATIVE_INTEGER, "xs:negativeInteger");
1✔
309
        defineBuiltInType(LONG, "xs:long");
1✔
310
        defineBuiltInType(INT, "xs:int");
1✔
311
        defineBuiltInType(SHORT, "xs:short");
1✔
312
        defineBuiltInType(BYTE, "xs:byte");
1✔
313
        defineBuiltInType(NON_NEGATIVE_INTEGER, "xs:nonNegativeInteger");
1✔
314
        defineBuiltInType(UNSIGNED_LONG, "xs:unsignedLong");
1✔
315
        defineBuiltInType(UNSIGNED_INT, "xs:unsignedInt");
1✔
316
        defineBuiltInType(UNSIGNED_SHORT, "xs:unsignedShort");
1✔
317
        defineBuiltInType(UNSIGNED_BYTE, "xs:unsignedByte");
1✔
318
        defineBuiltInType(POSITIVE_INTEGER, "xs:positiveInteger");
1✔
319
        defineBuiltInType(G_YEAR_MONTH, "xs:gYearMonth");
1✔
320
        defineBuiltInType(G_YEAR, "xs:gYear");
1✔
321
        defineBuiltInType(G_MONTH_DAY, "xs:gMonthDay");
1✔
322
        defineBuiltInType(G_DAY, "xs:gDay");
1✔
323
        defineBuiltInType(G_MONTH, "xs:gMonth");
1✔
324
        defineBuiltInType(STRING, "xs:string");
1✔
325
        defineBuiltInType(NORMALIZED_STRING, "xs:normalizedString");
1✔
326
        defineBuiltInType(TOKEN, "xs:token");
1✔
327
        defineBuiltInType(LANGUAGE, "xs:language");
1✔
328
        defineBuiltInType(NMTOKEN, "xs:NMTOKEN");
1✔
329
        defineBuiltInType(NAME, "xs:Name");
1✔
330
        defineBuiltInType(NCNAME, "xs:NCName");
1✔
331
        defineBuiltInType(ID, "xs:ID");
1✔
332
        defineBuiltInType(IDREF, "xs:IDREF");
1✔
333
        defineBuiltInType(ENTITY, "xs:ENTITY");
1✔
334
        defineBuiltInType(BOOLEAN, "xs:boolean");
1✔
335
        defineBuiltInType(BASE64_BINARY, "xs:base64Binary");
1✔
336
        defineBuiltInType(HEX_BINARY, "xs:hexBinary");
1✔
337
        defineBuiltInType(ANY_URI, "xs:anyURI");
1✔
338
        defineBuiltInType(QNAME, "xs:QName");
1✔
339
        defineBuiltInType(NOTATION, "xs:NOTATION");
1✔
340
        defineBuiltInType(NMTOKENS, "xs:NMTOKENS");
1✔
341
        defineBuiltInType(IDREFS, "xs:IDREFS");
1✔
342
        defineBuiltInType(ENTITIES, "xs:ENTITIES");
1✔
343
        defineBuiltInType(NUMERIC, "xs:numeric", "numeric");                                        // keep `numeric` for backward compatibility
1✔
344
        defineBuiltInType(ERROR, "xs:error");
1✔
345
        defineBuiltInType(UNTYPED, "xs:untyped");
1✔
346
        defineBuiltInType(NODE, "node()");
1✔
347
        defineBuiltInType(ATTRIBUTE, "attribute()");
1✔
348
        defineBuiltInType(COMMENT, "comment()");
1✔
349
        defineBuiltInType(DOCUMENT, "document-node()");
1✔
350
        defineBuiltInType(ELEMENT, "element()");
1✔
351
        defineBuiltInType(NAMESPACE, "namespace()");
1✔
352
        defineBuiltInType(PROCESSING_INSTRUCTION, "processing-instruction()");
1✔
353
        defineBuiltInType(TEXT, "text()");
1✔
354
        defineBuiltInType(FUNCTION, "function(*)", "function");
1✔
355
        defineBuiltInType(ARRAY_ITEM, "array(*)", "array");
1✔
356
        defineBuiltInType(MAP_ITEM, "map(*)", "map");                                               // keep `map` for backward compatibility
1✔
357
        defineBuiltInType(CDATA_SECTION, "cdata-section()");
1✔
358
        defineBuiltInType(JAVA_OBJECT, "object");
1✔
359
        defineBuiltInType(EMPTY_SEQUENCE, "empty-sequence()", "empty()");                           // keep `empty()` for backward compatibility
1✔
360

361
        // reduce any unused space
362
        typeNames.trim();
1✔
363
        typeCodes.trim();
1✔
364
    }
365

366
    static {
367
        defineUnionType(NUMERIC, new int[]{ DECIMAL, FLOAT, DOUBLE });
1✔
368
        defineUnionType(ERROR, new int[0] );
1✔
369
    }
370

371
    // https://www.w3.org/TR/xmlschema-2/#built-in-primitive-datatypes
372
    static {
373
        definePrimitiveType(STRING, new int[] {
1✔
374
                NORMALIZED_STRING,
1✔
375
                TOKEN,
1✔
376
                LANGUAGE,
1✔
377
                NMTOKEN,
1✔
378
                NAME,
1✔
379
                NCNAME,
1✔
380
                ID,
1✔
381
                IDREF,
1✔
382
                ENTITY
1✔
383
        });
384
        definePrimitiveType(BOOLEAN);
1✔
385
        definePrimitiveType(DECIMAL, new int[] {
1✔
386
                INTEGER,
1✔
387
                NON_POSITIVE_INTEGER,
1✔
388
                NEGATIVE_INTEGER,
1✔
389
                LONG,
1✔
390
                INT,
1✔
391
                SHORT,
1✔
392
                BYTE,
1✔
393
                NON_NEGATIVE_INTEGER,
1✔
394
                UNSIGNED_LONG,
1✔
395
                UNSIGNED_INT,
1✔
396
                UNSIGNED_SHORT,
1✔
397
                UNSIGNED_BYTE,
1✔
398
                POSITIVE_INTEGER
1✔
399
        });
400
        definePrimitiveType(FLOAT);
1✔
401
        definePrimitiveType(DOUBLE);
1✔
402
        definePrimitiveType(DURATION, new int[] {
1✔
403
                YEAR_MONTH_DURATION,
1✔
404
                DAY_TIME_DURATION
1✔
405
        });
406
        definePrimitiveType(DATE_TIME, new int[] {
1✔
407
                DATE_TIME_STAMP
1✔
408
        });
409
        definePrimitiveType(TIME);
1✔
410
        definePrimitiveType(DATE);
1✔
411
        definePrimitiveType(G_YEAR_MONTH);
1✔
412
        definePrimitiveType(G_YEAR);
1✔
413
        definePrimitiveType(G_MONTH_DAY);
1✔
414
        definePrimitiveType(G_DAY);
1✔
415
        definePrimitiveType(G_MONTH);
1✔
416
        definePrimitiveType(HEX_BINARY);
1✔
417
        definePrimitiveType(BASE64_BINARY);
1✔
418
        definePrimitiveType(ANY_URI);
1✔
419
        definePrimitiveType(QNAME);
1✔
420
        definePrimitiveType(NOTATION);
1✔
421

422
        // reduce any unused space
423
        primitiveTypes.trim();
1✔
424
    }
1✔
425

426
    /**
427
     * Define built-in type.
428
     *
429
     * @param type the type constant
430
     * @param name The first name is the default name, any other names are aliases.
431
     */
432
    private static void defineBuiltInType(final int type, final String... name) {
433
        typeNames.put(type, name);
1✔
434
        for (final String n : name) {
1✔
435
            typeCodes.put(n, type);
1✔
436
        }
437
    }
1✔
438

439
    /**
440
     * Define supertype/subtype relation.
441
     *
442
     * @param supertype type constant of the super type
443
     * @param subtype the subtype
444
     */
445
    private static void defineSubType(final int supertype, final int subtype) {
446
        superTypes[subtype] = supertype;
1✔
447
    }
1✔
448

449
    /**
450
     * Define a union type.
451
     *
452
     * @param unionType the union type
453
     * @param memberTypes the members of the union type
454
     */
455
    private static void defineUnionType(final int unionType, final int... memberTypes) {
456
        unionTypes.put(unionType, new IntArraySet(memberTypes));
1✔
457
    }
1✔
458

459
    /**
460
     * Define a primitive type.
461
     *
462
     * @param primitiveType the primitive type
463
     * @param subTypes the subtypes of the primitive type
464
     */
465
    private static void definePrimitiveType(final int primitiveType, final int... subTypes) {
466
        for (final int subType : subTypes) {
1✔
467
            primitiveTypes.put(subType, primitiveType);
1✔
468
        }
469

470
        // primitive type of a primitive type is itself!
471
        primitiveTypes.put(primitiveType, primitiveType);
1✔
472
    }
1✔
473

474
    /**
475
     * Get the internal default name for the built-in type.
476
     *
477
     * @param type the type constant
478
     * @return name of the type
479
     */
480
    public static @Nullable String getTypeName(final int type) {
481
        final String[] names = typeNames.get(type);
1✔
482
        if (names != null) {
1!
483
            return names[0];
1✔
484
        }
485
        return null;
×
486
    }
487

488
    /**
489
     * Get the internal aliases for the built-in type.
490
     *
491
     * @param type the type constant
492
     * @return one or more alias names
493
     */
494
    public static @Nullable String[] getTypeAliases(final int type) {
495
        final String names[] = typeNames.get(type);
×
496
        if (names != null && names.length > 1) {
×
497
            final String aliases[] = new String[names.length - 1];
×
498
            System.arraycopy(names, 1, aliases, 0, names.length - 1);
×
499
            return aliases;
×
500
        }
501
        return null;
×
502
    }
503

504
    /**
505
     * Get the type code for a type identified by its internal name.
506
     *
507
     * @param name name of the type
508
     * @return type constant
509
     * @throws XPathException in case of dynamic error
510
     */
511
    public static int getType(final String name) throws XPathException {
512
        final int code = typeCodes.getInt(name);
1✔
513
        if (code == NO_SUCH_VALUE) {
1✔
514
            throw new XPathException((Expression) null, "Type: " + name + " is not defined");
1✔
515
        }
516
        return code;
1✔
517
    }
518

519
    /**
520
     * Get the type code for a type identified by its QName.
521
     *
522
     * @param qname name of the type
523
     * @return type constant
524
     * @throws XPathException in case of dynamic error
525
     */
526
    public static int getType(final QName qname) throws XPathException {
527
        final String uri = qname.getNamespaceURI();
1✔
528
        return switch (uri) {
1!
529
            case Namespaces.SCHEMA_NS -> getType("xs:" + qname.getLocalPart());
1✔
530
            case Namespaces.XPATH_DATATYPES_NS -> getType("xdt:" + qname.getLocalPart());
1✔
531
            default -> getType(qname.getLocalPart());
×
532
        };
533
    }
534

535
    /**
536
     * Check if the given type code is a subtype of the specified supertype.
537
     *
538
     * @param subtype the type constant of the subtype
539
     * @param supertype type constant of the super type
540
     *
541
     * @return true if subtype is a sub type of supertype
542
     *
543
     * @throws IllegalArgumentException When the type is invalid
544
     */
545
    public static boolean subTypeOf(int subtype, final int supertype) {
546
        if (subtype == supertype) {
1✔
547
            return true;
1✔
548
        }
549

550
        if (supertype == ITEM || supertype == ANY_TYPE) {
1✔
551
            // Note: this will return true even if subtype == EMPTY_SEQUENCE, maybe return subtype != EMPTY_SEQUENCE ?
552
            return true;
1✔
553
        }
554

555
        // Note that EMPTY_SEQUENCE is *not* a sub-type of anything else than itself
556
        // EmptySequence has to take care of this when it checks its type
557
        if (subtype == ITEM || subtype == EMPTY_SEQUENCE || subtype == ANY_TYPE || subtype == NODE) {
1✔
558
            return false;
1✔
559
        }
560

561
        if (unionTypes.containsKey(supertype)) {
1✔
562
            return subTypeOfUnion(subtype, supertype);
1✔
563
        }
564
        if (unionTypes.containsKey(subtype)) {
1✔
565
            return unionMembersHaveSuperType(subtype, supertype);
1✔
566
        }
567

568
        subtype = superTypes[subtype];
1✔
569
        if (subtype == 0) {
1!
570
            throw new IllegalArgumentException(
×
571
                    "type " + subtype + " is not a valid type");
×
572
        }
573
        return subTypeOf(subtype, supertype);
1✔
574
    }
575

576
    /**
577
     * Get the type code of the supertype of the specified subtype.
578
     *
579
     * @param subtype type code of the sub type
580
     * @return type constant for the super type
581
     *
582
     * @throws IllegalArgumentException if {@code subtype} has no defined super type
583
     */
584
    public static int getSuperType(final int subtype) {
585
        if (subtype == ITEM || subtype == NODE) {
1✔
586
            return ITEM;
1✔
587
        } else if (subtype == ANY_TYPE) {
1!
588
            return subtype;
×
589
        }
590

591
        if (subtype >= superTypes.length) {
1!
592
            // Note that EMPTY_SEQUENCE is *not* a sub-type of anything else than itself
593
            throw new IllegalArgumentException("Type: " + subtype + " has no super types defined");
×
594
        }
595

596
        final int supertype = superTypes[subtype];
1✔
597
        if (supertype == 0) {
1!
598
            LOG.warn("Elemental does not define a super-type for the sub-type {}", getTypeName(subtype), new Throwable());
×
599
            return ITEM;
×
600
        }
601

602
        return supertype;
1✔
603
    }
604

605
    /**
606
     * Find a common supertype for two given type codes.
607
     *
608
     * Type.ITEM is returned if no other common supertype
609
     * is found.
610
     *
611
     * @param type1 type constant for the first type
612
     * @param type2 type constant for the second type
613
     * @return common super type or {@link Type#ITEM} if none
614
     */
615
    public static int getCommonSuperType(final int type1, final int type2) {
616
        //Super shortcut
617
        if (type1 == type2) {
1✔
618
            return type1;
1✔
619
        }
620
        // if one of the types is empty(), return the other type: optimizer is free to choose
621
        // an optimization based on the more specific type.
622
        if (type1 == Type.EMPTY_SEQUENCE) {
1!
623
            return type2;
×
624
        } else if (type2 == Type.EMPTY_SEQUENCE) {
1!
625
            return type1;
×
626
        }
627

628
        if (unionTypes.containsKey(type1) && subTypeOfUnion(type2, type1)) {
1!
629
            return type2;
×
630
        }
631
        if (unionTypes.containsKey(type2) && subTypeOfUnion(type1, type2)) {
1!
632
            return type1;
×
633
        }
634

635
        //TODO : optimize by swapping the arguments based on their numeric values ?
636
        //Processing lower value first *should* reduce the size of the Set
637
        //Collect type1's super-types
638
        final IntSet t1 = new IntOpenHashSet(11, Hash.VERY_FAST_LOAD_FACTOR);
1✔
639
        //Don't introduce a shortcut (starting at getSuperType(type1) here
640
        //type2 might be a super-type of type1
641
        int t;
642
        for (t = type1; t != ITEM && t != ANY_TYPE; t = getSuperType(t)) {
1!
643
            //Shortcut
644
            if (t == type2) {
1✔
645
                return t;
1✔
646
            }
647
            t1.add(t);
1✔
648
        }
649
        //Starting from type2's super type : the shortcut should have done its job
650
        for (t = getSuperType(type2); t != ITEM && t != ANY_TYPE; t = getSuperType(t)) {
1!
651
            if (t1.contains(t)) {
1✔
652
                return t;
1✔
653
            }
654
        }
655
        return t;
1✔
656
    }
657

658
    /**
659
     * Determines if a union type has an other type as a member.
660
     *
661
     * @param unionType the union type
662
     * @param other the type to test for union membership
663
     *
664
     * @return true if the type is a member, false otherwise.
665
     */
666
    public static boolean hasMember(final int unionType, final int other) {
667
        final IntArraySet members = unionTypes.get(unionType);
1✔
668
        if (members == null) {
1✔
669
            return false;
1✔
670
        }
671
        return members.contains(other);
1✔
672
    }
673

674
    /**
675
     * Check if the given type is a subtype of a member of the specified union type.
676
     *
677
     * @param subtype the type constant of the subtype
678
     * @param unionType the union type
679
     *
680
     * @return true if subtype is a sub type of a member of the union type
681
     */
682
    public static boolean subTypeOfUnion(final int subtype, final int unionType) {
683
        final IntArraySet members = unionTypes.get(unionType);
1✔
684
        if (members == null) {
1!
685
            return false;
×
686
        }
687

688
        // inherited behaviour from {@link #subTypeOf(int, int)}
689
        // where type is considered a subtype of itself.
690
        if (subtype == unionType) {
1✔
691
            return true;
1✔
692
        }
693

694
        // quick optimisation for: subtype = member
695
        if (members.contains(subtype)) {
1✔
696
            return true;
1✔
697
        }
698

699
        for (final int member : members) {
1✔
700
            if (subTypeOf(subtype, member)) {
1✔
701
                return true;
1✔
702
            }
703
        }
704
        return false;
1✔
705
    }
706

707
    public static boolean unionMembersHaveSuperType(final int unionType, final int supertype) {
708
        final IntArraySet members = unionTypes.get(unionType);
1✔
709
        if (members == null || members.size() == 0) {
1!
710
            return false;
×
711
        }
712

713
        // inherited behaviour from {@link #subTypeOf(int, int)}
714
        // where type is considered a subtype of itself.
715
        if (supertype == unionType) {
1!
716
            return true;
×
717
        }
718

719
        for (final int member : members) {
1✔
720
            if (!subTypeOf(member, supertype)) {
1✔
721
                return false;
1✔
722
            }
723
        }
724

725
        return true;
1✔
726
    }
727

728
    /**
729
     * Gets the primitive type for a typed atomic type.
730
     *
731
     * @param type the type to retrieve the primitive type of
732
     *
733
     * @return the primitive type
734
     *
735
     * @throws IllegalArgumentException if {@code type} has no defined primitive type
736
     */
737
    public static int primitiveTypeOf(final int type) throws IllegalArgumentException {
738
        final int primitiveType = primitiveTypes.get(type);
1✔
739
        if (primitiveType == NO_SUCH_VALUE) {
1!
740
            final String typeName = getTypeName(type);
×
741
            throw new IllegalArgumentException("Primitive type is not defined for: " + (typeName != null ? typeName : type));
×
742
        }
743
        return primitiveType;
1✔
744
    }
745

746
    /**
747
     * Get the XDM equivalent type of a DOM Node type (i.e. {@link Node#getNodeType()}).
748
     *
749
     * @param domNodeType the DOM node type as defined in {@link Node}.
750
     *
751
     * @return the equivalent XDM type.
752
     *
753
     * @throws IllegalArgumentException if the provided argument is not a DOM Node Type.
754
     */
755
    public static int fromDomNodeType(final short domNodeType) {
756
        switch (domNodeType) {
1!
757
            case Node.ELEMENT_NODE:
758
                return Type.ELEMENT;
1✔
759
            case Node.ATTRIBUTE_NODE:
760
                return Type.ATTRIBUTE;
1✔
761
            case Node.TEXT_NODE:
762
                return Type.TEXT;
1✔
763
            case Node.CDATA_SECTION_NODE:
764
                return Type.CDATA_SECTION;
1✔
765
            case Node.PROCESSING_INSTRUCTION_NODE:
766
                return Type.PROCESSING_INSTRUCTION;
1✔
767
            case Node.COMMENT_NODE:
768
                return Type.COMMENT;
1✔
769
            case Node.DOCUMENT_NODE:
770
                return Type.DOCUMENT;
1✔
771

772
            // un-mappable Node types, so just return the XDM Node type
773
            case Node.ENTITY_REFERENCE_NODE:
774
            case Node.ENTITY_NODE:
775
            case Node.DOCUMENT_TYPE_NODE:
776
            case Node.DOCUMENT_FRAGMENT_NODE:
777
            case Node.NOTATION_NODE:
778
                return Type.NODE;
×
779

780
            // unknown
781
            default:
782
                throw new IllegalArgumentException("Unknown DOM Node type: " + domNodeType);
×
783
        }
784
    }
785
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc