From 3689a3535b2162dc54fc78c5d2b7f6f9ec88f2b6 Mon Sep 17 00:00:00 2001 From: Gunther Rademacher Date: Tue, 17 Mar 2026 09:20:31 +0100 Subject: [PATCH] implement subtyping rules for choice item types --- .../basex/io/parse/csv/CsvW3Converter.java | 3 +- .../java/org/basex/query/QueryParser.java | 2 +- .../java/org/basex/query/func/Function.java | 6 +- .../java/org/basex/query/func/Records.java | 2 +- .../basex/query/func/fn/FnInvisibleXml.java | 4 +- .../query/func/fn/FnNodeTypeAnnotation.java | 2 +- .../query/value/type/ChoiceItemType.java | 165 ++++++++---------- .../basex/query/value/type/RecordType.java | 4 +- .../org/basex/query/value/type/SeqType.java | 13 +- .../org/basex/query/value/type/Types.java | 33 +++- .../java/org/basex/query/SeqTypeTest.java | 47 +++-- 11 files changed, 151 insertions(+), 130 deletions(-) diff --git a/basex-core/src/main/java/org/basex/io/parse/csv/CsvW3Converter.java b/basex-core/src/main/java/org/basex/io/parse/csv/CsvW3Converter.java index c064402203..1cdbbb760f 100644 --- a/basex-core/src/main/java/org/basex/io/parse/csv/CsvW3Converter.java +++ b/basex-core/src/main/java/org/basex/io/parse/csv/CsvW3Converter.java @@ -121,7 +121,8 @@ private static FuncItem funcItem(final Value rows, final XQMap columnIndex, final QueryContext qc, final InputInfo ii) { final VarScope vs = new VarScope(); final SeqType rowType = POSITIVE_INTEGER_O; - final SeqType colType = ChoiceItemType.get(STRING_O, POSITIVE_INTEGER_O).seqType(); + final SeqType colType = ChoiceItemType.get(BasicType.STRING, + BasicType.POSITIVE_INTEGER).seqType(); final Var row = vs.addNew(new QNm("row"), rowType, qc, ii); final Var col = vs.addNew(new QNm("column"), colType, qc, ii); final Get get = new Get(ii, rows, columnIndex, new VarRef(ii, row), new VarRef(ii, col)); diff --git a/basex-core/src/main/java/org/basex/query/QueryParser.java b/basex-core/src/main/java/org/basex/query/QueryParser.java index 279a8c6d8c..e7b52227ab 100644 --- a/basex-core/src/main/java/org/basex/query/QueryParser.java +++ b/basex-core/src/main/java/org/basex/query/QueryParser.java @@ -3805,7 +3805,7 @@ private EnumType enumerationType() throws QueryException { private SeqType choiceItemType() throws QueryException { final ChoiceItemType.Builder builder = new ChoiceItemType.Builder(); do { - builder.add(itemType()); + builder.add(itemType().type); } while(wsConsume("|")); check(')'); return builder.build().seqType(); diff --git a/basex-core/src/main/java/org/basex/query/func/Function.java b/basex-core/src/main/java/org/basex/query/func/Function.java index 67fefcd34e..5e227620da 100644 --- a/basex-core/src/main/java/org/basex/query/func/Function.java +++ b/basex-core/src/main/java/org/basex/query/func/Function.java @@ -238,7 +238,7 @@ public enum Function implements AFunction { params(ELEMENT_ZO, MAP_ZO), ITEM_ZO.mapType(BasicType.STRING).seqType(Occ.ZERO_OR_ONE)), /** XQuery function. */ ELEMENT_TO_MAP_PLAN(FnElementToMapPlan::new, "element-to-map-plan(input)", - params(ChoiceItemType.get(DOCUMENT_O, ELEMENT_O).seqType(Occ.ZERO_OR_MORE)), + params(ChoiceItemType.get(NodeType.DOCUMENT, NodeType.ELEMENT).seqType(Occ.ZERO_OR_MORE)), RECORD_O.mapType(BasicType.STRING).seqType()), /** XQuery function. */ ELEMENT_WITH_ID(FnElementWithId::new, "element-with-id(values[,node])", @@ -385,7 +385,7 @@ public enum Function implements AFunction { /** XQuery function. */ IN_SCOPE_NAMESPACES(FnInScopeNamespaces::new, "in-scope-namespaces(element)", params(ELEMENT_O), - ANY_URI_O.mapType(ChoiceItemType.get(NCNAME_O, EnumType.get("").seqType())).seqType()), + ANY_URI_O.mapType(ChoiceItemType.get(BasicType.NCNAME, EnumType.get(""))).seqType()), /** XQuery function. */ IN_SCOPE_PREFIXES(FnInScopePrefixes::new, "in-scope-prefixes(element)", params(ELEMENT_O), STRING_ZM), @@ -511,7 +511,7 @@ public enum Function implements AFunction { params(NODE_ZO), QNAME_ZO), /** XQuery function. */ NODE_TYPE_ANNOTATION(FnNodeTypeAnnotation::new, "node-type-annotation(node)", - params(ChoiceItemType.get(ELEMENT_O, ATTRIBUTE_O).seqType()), + params(ChoiceItemType.get(NodeType.ELEMENT, NodeType.ATTRIBUTE).seqType()), Records.SCHEMA_TYPE.get().seqType()), /** XQuery function. */ NORMALIZE_SPACE(FnNormalizeSpace::new, "normalize-space([value])", diff --git a/basex-core/src/main/java/org/basex/query/func/Records.java b/basex-core/src/main/java/org/basex/query/func/Records.java index b19b937d48..ee03a14acb 100644 --- a/basex-core/src/main/java/org/basex/query/func/Records.java +++ b/basex-core/src/main/java/org/basex/query/func/Records.java @@ -50,7 +50,7 @@ public enum Records { field("column-index", MapType.get(BasicType.STRING, Types.INTEGER_O).seqType(Occ.ZERO_OR_ONE)), field("rows", ArrayType.get(Types.STRING_O).seqType(Occ.ZERO_OR_MORE)), field("get", FuncType.get(Types.STRING_O, Types.POSITIVE_INTEGER_O, - ChoiceItemType.get(Types.POSITIVE_INTEGER_O, Types.STRING_O).seqType()).seqType())), + ChoiceItemType.get(BasicType.POSITIVE_INTEGER, BasicType.STRING).seqType()).seqType())), /** Record definition. */ RANDOM_NUMBER_GENERATOR(FN_URI, "random-number-generator"), /** Record definition. */ diff --git a/basex-core/src/main/java/org/basex/query/func/fn/FnInvisibleXml.java b/basex-core/src/main/java/org/basex/query/func/fn/FnInvisibleXml.java index 290059cc85..7d7c982c16 100644 --- a/basex-core/src/main/java/org/basex/query/func/fn/FnInvisibleXml.java +++ b/basex-core/src/main/java/org/basex/query/func/fn/FnInvisibleXml.java @@ -29,8 +29,8 @@ */ public final class FnInvisibleXml extends StandardFunc { /** The function's argument type. */ - public static final SeqType ARG_TYPE = ChoiceItemType.get(Types.STRING_O, - NodeType.get(NameTest.get(new QNm("ixml"))).seqType()).seqType(Occ.ZERO_OR_ONE); + public static final SeqType ARG_TYPE = ChoiceItemType.get(BasicType.STRING, + NodeType.get(NameTest.get(new QNm("ixml")))).seqType(Occ.ZERO_OR_ONE); /** The invisible XML parser generator. */ private Generator generator; diff --git a/basex-core/src/main/java/org/basex/query/func/fn/FnNodeTypeAnnotation.java b/basex-core/src/main/java/org/basex/query/func/fn/FnNodeTypeAnnotation.java index 6ddd6feee8..3822d218a6 100644 --- a/basex-core/src/main/java/org/basex/query/func/fn/FnNodeTypeAnnotation.java +++ b/basex-core/src/main/java/org/basex/query/func/fn/FnNodeTypeAnnotation.java @@ -16,7 +16,7 @@ public final class FnNodeTypeAnnotation extends FnSchemaType { /** The function's argument type. */ private static final SeqType ARG_TYPE = - ChoiceItemType.get(Types.ELEMENT_O, Types.ATTRIBUTE_O).seqType(); + ChoiceItemType.get(NodeType.ELEMENT, NodeType.ATTRIBUTE).seqType(); @Override public Value value(final QueryContext qc) throws QueryException { diff --git a/basex-core/src/main/java/org/basex/query/value/type/ChoiceItemType.java b/basex-core/src/main/java/org/basex/query/value/type/ChoiceItemType.java index 6cfaf1d0b3..89564818ee 100644 --- a/basex-core/src/main/java/org/basex/query/value/type/ChoiceItemType.java +++ b/basex-core/src/main/java/org/basex/query/value/type/ChoiceItemType.java @@ -4,9 +4,8 @@ import java.util.*; -import org.basex.io.in.DataInput; +import org.basex.io.in.*; import org.basex.query.*; -import org.basex.query.expr.path.*; import org.basex.query.value.*; import org.basex.query.value.item.*; import org.basex.util.*; @@ -19,7 +18,7 @@ */ public final class ChoiceItemType implements Type { /** Alternative item types. */ - public final List types; + public final List types; /** Common ancestor type. */ private final Type union; @@ -30,13 +29,13 @@ public final class ChoiceItemType implements Type { * Constructor. * @param types alternative item types */ - private ChoiceItemType(final List types) { + private ChoiceItemType(final List types) { this.types = types; - Type tp = null; - for(final SeqType st : this.types) { - tp = tp == null ? st.type : tp.union(st.type); + Type ut = null; + for(final Type tp : this.types) { + ut = ut == null ? tp : ut.union(tp); } - union = tp; + union = ut; } /** @@ -44,17 +43,17 @@ private ChoiceItemType(final List types) { * @param types alternative item types * @return choice item type */ - public static Type get(final SeqType... types) { + public static Type get(final Type... types) { final Builder builder = new Builder(); - for(final SeqType st : types) builder.add(st); + for(final Type tp : types) builder.add(tp); return builder.build(); } @Override public Value cast(final Item item, final QueryContext qc, final InputInfo info) throws QueryException { - for(final SeqType st : types) { - final Value val = st.cast(item, false, qc, info); + for(final Type tp : types) { + final Value val = tp.seqType().cast(item, false, qc, info); if(val != null) return val; } throw FUNCCAST_X_X_X.get(info, item.type, this, item); @@ -63,9 +62,9 @@ public Value cast(final Item item, final QueryContext qc, final InputInfo info) @Override public Value cast(final Object value, final QueryContext qc, final InputInfo info) throws QueryException { - for(final SeqType st : types) { + for(final Type tp : types) { try { - return st.type.cast(value, qc, info); + return tp.cast(value, qc, info); } catch(final QueryException ex) { Util.debug(ex); } @@ -90,25 +89,48 @@ public boolean eq(final Type type) { return this == type || type instanceof final ChoiceItemType cit && types.equals(cit.types); } + @Override + public boolean instanceOf(final Type type) { + final Type norm = expand(type); + if(norm instanceof final ChoiceItemType ct) { + for(final Type tp : types) { + if(!ct.hasInstance(tp)) return false; + } + } else { + for(final Type tp : types) { + if(!tp.instanceOf(norm)) return false; + } + } + return true; + } + /** - * Checks if this choice item type is an instance of the specified sequence type. - * @param seqType sequence type to check + * Checks if this choice type is a supertype of the given type. + * @param type type to be checked * @return result of check */ - public boolean instanceOf(final SeqType seqType) { - if(!seqType.one()) throw Util.notExpected(); - for(final SeqType st : types) { - if(!st.instanceOf(seqType)) return false; + boolean hasInstance(final Type type) { + final Type norm = expand(type); + if(norm instanceof final ChoiceItemType ct) return ct.instanceOf(this); + for(final Type tp : types) { + if(norm.instanceOf(tp)) return true; } - return true; + return false; } - @Override - public boolean instanceOf(final Type type) { - for(final SeqType st : types) { - if(!st.type.instanceOf(type)) return false; - } - return true; + /** + * Expand the given type for comparison with choice item types, if necessary, as specified in the + * subtyping rules for choice item types. + * @param type type to expand + * @return expanded type + */ + private static Type expand(final Type type) { + if(type == BasicType.NUMERIC) return Types.NUMERIC_EXPANSION; + if(type == BasicType.ANY_ATOMIC_TYPE) return Types.ANY_ATOMIC_TYPE_EXPANSION; + if(type == BasicType.ITEM) return Types.ITEM_EXPANSION; + if(type == NodeType.NODE) return Types.NODE_EXPANSION; + if(type == NodeType.GNODE) return Types.GNODE_EXPANSION; + return type; } @Override @@ -119,9 +141,9 @@ public Type union(final Type type) { @Override public Type intersect(final Type type) { final Builder builder = new Builder(); - for(final SeqType st : types) { - final Type tp = type.intersect(st.type); - if(tp != null) builder.add(tp.seqType()); + for(final Type tp : types) { + final Type is = type.intersect(tp); + if(is != null) builder.add(is); } return builder.types.isEmpty() ? null : builder.build(); } @@ -133,7 +155,7 @@ public boolean isNumber() { @Override public boolean isUntyped() { - return union.isNumberOrUntyped(); + return union.isUntyped(); } @Override @@ -163,41 +185,8 @@ public ID id() { @Override public boolean nsSensitive() { - for(final SeqType st : types) { - if(st.type.nsSensitive()) return true; - } - return false; - } - - /** - * Checks if the given type is an instance of this type. - * @param type type to be checked - * @return result of check - */ - boolean hasInstance(final Type type) { - for(final SeqType st : types) { - if(type.instanceOf(st.type)) return true; - } - return false; - } - - /** - * Checks if the given sequence type is an instance of this type. - * @param seqType sequence type to be checked - * @return result of check - */ - boolean hasInstance(final SeqType seqType) { - if(!seqType.one()) throw Util.notExpected(); - if(seqType.type instanceof final NodeType nt) { - if(nt.test instanceof final UnionTest ut) { - for(final Test t : ut.tests) { - if(!hasInstance(NodeType.get(t))) return false; - } - return true; - } - } - for(final SeqType st : types) { - if(seqType.instanceOf(st)) return true; + for(final Type tp : types) { + if(tp.nsSensitive()) return true; } return false; } @@ -219,7 +208,7 @@ public String name() { @Override public String toString() { - return toString("|", (Object[]) types.toArray(SeqType[]::new)); + return toString("|", (Object[]) types.toArray(Type[]::new)); } /** @@ -229,66 +218,66 @@ public String toString() { */ public static final class Builder { /** Alternative item types. */ - private final ArrayList types = new ArrayList<>(); + private final ArrayList types = new ArrayList<>(); /** * Builds and returns the resulting choice item type. * @return choice item type, or the single item type if the list contains only one type */ public Type build() { - if(types.size() != 1) types.remove(Types.ERROR_O); + if(types.size() != 1) types.remove(BasicType.ERROR); return switch(types.size()) { case 0 -> throw Util.notExpected(); - case 1 -> types.get(0).type; + case 1 -> types.get(0); default -> new ChoiceItemType(types); }; } /** - * Adds the specified sequence type to this builder, merging enum types only if consecutive, and - * merging document, element, attribute, and pi types anywhere in the list, ignoring duplicates, - * and flattening nested ChoiceItemTypes. - * @param st sequence type to be added + * Adds the specified type to this builder, merging enum types only if consecutive, and merging + * document, element, attribute, and pi types anywhere in the list, ignoring duplicates, and + * flattening nested ChoiceItemTypes. + * @param type type to be added * @return this builder */ - public Builder add(final SeqType st) { + public Builder add(final Type type) { // flatten nested ChoiceItemTypes - if(st.type instanceof ChoiceItemType ct) { - for(final SeqType s : ct.types) add(s); + if(type instanceof final ChoiceItemType ct) { + for(final Type tp : ct.types) add(tp); return this; } // ignore duplicates - if(types.contains(st)) return this; + if(types.contains(type)) return this; // non-mergeable types or first entry - final Type.ID id = st.type.id(); + final Type.ID id = type.id(); if(types.isEmpty() || !id.oneOf(Type.ID.ENM, Type.ID.DOC, Type.ID.ELM, Type.ID.ATT, Type.ID.PI)) { - types.add(st); + types.add(type); return this; } // enums: merge consecutive entries only, to preserve position of alternatives if(id == Type.ID.ENM) { final int last = types.size() - 1; - final Type tp = types.get(last).type; + final Type tp = types.get(last); if(tp.id() == Type.ID.ENM) { // remove and re-add, for duplicate removal types.remove(last); - return add(tp.union(st.type).seqType()); + return add(tp.union(type)); } - // not consecutive: add as-is - types.add(st); + // not consecutive: add as-is + types.add(type); return this; } // nodes (DOC/ELM/ATT/PI): merge with existing alternative of same kind anywhere, in-place for(int i = 0; i < types.size(); i++) { - final SeqType existing = types.get(i); - if(existing.type.id() == id) { - types.set(i, existing.type.union(st.type).seqType()); + final Type existing = types.get(i); + if(existing.id() == id) { + types.set(i, existing.union(type)); return this; } } // no existing node kind found - types.add(st); + types.add(type); return this; } } diff --git a/basex-core/src/main/java/org/basex/query/value/type/RecordType.java b/basex-core/src/main/java/org/basex/query/value/type/RecordType.java index b9ebf8bd68..4ec60d9ac6 100644 --- a/basex-core/src/main/java/org/basex/query/value/type/RecordType.java +++ b/basex-core/src/main/java/org/basex/query/value/type/RecordType.java @@ -206,8 +206,8 @@ private boolean instanceOf(final Type type, final Set pairs) { return true; } if(type instanceof final ChoiceItemType cit) { - for(final SeqType st : cit.types) { - if(instanceOf(st.type, pairs)) return true; + for(final Type tp : cit.types) { + if(instanceOf(tp, pairs)) return true; } return false; } diff --git a/basex-core/src/main/java/org/basex/query/value/type/SeqType.java b/basex-core/src/main/java/org/basex/query/value/type/SeqType.java index 6987b51092..00fec3f4c1 100644 --- a/basex-core/src/main/java/org/basex/query/value/type/SeqType.java +++ b/basex-core/src/main/java/org/basex/query/value/type/SeqType.java @@ -134,8 +134,8 @@ private boolean instance(final Value value, final boolean coerce) { */ public boolean instance(final Item item, final boolean coerce) { if(type instanceof final ChoiceItemType cit) { - for(final SeqType tp : cit.types) { - if(tp.instance(item, coerce)) return true; + for(final Type tp : cit.types) { + if(tp.seqType().instance(item, coerce)) return true; } return false; } @@ -260,9 +260,9 @@ private Value coerce(final Item item, final QNm name, final QueryContext qc, final CompileContext cc, final InputInfo info) throws QueryException { if(type instanceof final ChoiceItemType cit) { - for(final SeqType st : cit.types) { + for(final Type tp : cit.types) { try { - final Value value = st.coerce(item, name, qc, cc, info); + final Value value = tp.seqType().coerce(item, name, qc, cc, info); if(value != null) return value; } catch(final QueryException ex) { Util.debug(ex); @@ -460,9 +460,8 @@ public boolean instanceOf(final SeqType st) { // empty sequence: only check cardinality if(zero()) return !st.oneOrMore(); if(!occ.instanceOf(st.occ)) return false; - if(type instanceof final ChoiceItemType cit) return cit.instanceOf(st.with(EXACTLY_ONE)); - if(st.type instanceof final ChoiceItemType cit) return cit.hasInstance(with(EXACTLY_ONE)); - return type.instanceOf(st.type); + return st.type instanceof final ChoiceItemType cit ? cit.hasInstance(type) + : type.instanceOf(st.type); } /** diff --git a/basex-core/src/main/java/org/basex/query/value/type/Types.java b/basex-core/src/main/java/org/basex/query/value/type/Types.java index eeb03a24db..a9b4ec15ae 100644 --- a/basex-core/src/main/java/org/basex/query/value/type/Types.java +++ b/basex-core/src/main/java/org/basex/query/value/type/Types.java @@ -149,8 +149,7 @@ public final class Types { public static final SeqType BASE64_BINARY_ZM = BASE64_BINARY.seqType(ZERO_OR_MORE); /** String or xs:hex-binary or xs:base64-binary. */ - public static final Type STRING_OR_BINARY = - ChoiceItemType.get(STRING_O, HEX_BINARY_O, BASE64_BINARY_O); + public static final Type STRING_OR_BINARY = ChoiceItemType.get(STRING, HEX_BINARY, BASE64_BINARY); /** Single string or xs:hex-binary or xs:base64-binary. */ public static final SeqType STRING_OR_BINARY_O = STRING_OR_BINARY.seqType(); /** Zero or one string or xs:hex-binary or xs:base64-binary. */ @@ -188,6 +187,8 @@ public final class Types { public static final SeqType NAMESPACE_O = NAMESPACE.seqType(); /** Processing instruction. */ public static final SeqType PROCESSING_INSTRUCTION_O = PROCESSING_INSTRUCTION.seqType(); + /** One text node. */ + public static final SeqType TEXT_O = TEXT.seqType(); /** Zero or one text node. */ public static final SeqType TEXT_ZO = TEXT.seqType(ZERO_OR_ONE); /** Zero or more text nodes. */ @@ -204,9 +205,8 @@ public final class Types { public static final SeqType NMTOKENS_O = NMTOKENS.seqType(); /** Gregorian type. */ - public static final Type GREGORIAN = ChoiceItemType.get(DATE_TIME.seqType(), DATE.seqType(), - TIME.seqType(), G_YEAR.seqType(), G_YEAR_MONTH.seqType(), G_MONTH.seqType(), - G_MONTH_DAY.seqType(), G_DAY.seqType()); + public static final Type GREGORIAN = ChoiceItemType.get(DATE_TIME, DATE, TIME, + G_YEAR, G_YEAR_MONTH, G_MONTH, G_MONTH_DAY, G_DAY); /** Zero or one Gregorian. */ public static final SeqType GREGORIAN_ZO = GREGORIAN.seqType(ZERO_OR_ONE); @@ -250,7 +250,7 @@ public final class Types { public static final SeqType ARRAY_ZM = ARRAY.seqType(ZERO_OR_MORE); /** Map or array. */ - public static final Type MAP_OR_ARRAY = ChoiceItemType.get(MAP_O, ARRAY_O); + public static final Type MAP_OR_ARRAY = ChoiceItemType.get(MAP, ARRAY); /** Single map or array. */ public static final SeqType MAP_OR_ARRAY_O = MAP_OR_ARRAY.seqType(); /** Zero or more maps or arrays. */ @@ -275,6 +275,27 @@ public final class Types { /** Single empty record. */ public static final SeqType RECORD_O = RECORD.seqType(); + /** Expansion of xs:numeric for comparison with choice item types. */ + public static final Type NUMERIC_EXPANSION = ChoiceItemType.get(DOUBLE, FLOAT, DECIMAL); + /** Expansion of xs:anyAtomicType for comparison with choice item types. */ + public static final Type ANY_ATOMIC_TYPE_EXPANSION = ChoiceItemType.get(ANY_URI, BASE64_BINARY, + BOOLEAN, DATE, DATE_TIME, DECIMAL, DOUBLE, DURATION, FLOAT, G_DAY, G_MONTH, G_MONTH_DAY, + G_YEAR, G_YEAR_MONTH, HEX_BINARY, NOTATION, QNAME, STRING, TIME, UNTYPED_ATOMIC); + /** Expansion of node() for comparison with choice item types. */ + public static final Type NODE_EXPANSION = ChoiceItemType.get(DOCUMENT, ELEMENT, ATTRIBUTE, TEXT, + COMMENT, PROCESSING_INSTRUCTION, NAMESPACE); + /** Single expansion of node() for comparison with choice item types. */ + public static final SeqType NODE_EXPANSION_O = NODE_EXPANSION.seqType(); + /** Expansion of gnode() for comparison with choice item types. */ + public static final Type GNODE_EXPANSION = ChoiceItemType.get(NODE_EXPANSION, JNODE); + /** Single expansion of gnode() for comparison with choice item types. */ + public static final SeqType GNODE_EXPANSION_O = GNODE_EXPANSION.seqType(); + /** Expansion of item() for comparison with choice item types. */ + public static final Type ITEM_EXPANSION = ChoiceItemType.get(GNODE_EXPANSION, + ANY_ATOMIC_TYPE_EXPANSION, FUNCTION); + /** Single expansion of item() for comparison with choice item types. */ + public static final SeqType ITEM_EXPANSION_O = ITEM_EXPANSION.seqType(); + /** Indexed item types. */ private static final Type[] TYPES = new Type[Type.ID.LAST.asByte()]; diff --git a/basex-core/src/test/java/org/basex/query/SeqTypeTest.java b/basex-core/src/test/java/org/basex/query/SeqTypeTest.java index 1126fcbe31..1e93a1ee0e 100644 --- a/basex-core/src/test/java/org/basex/query/SeqTypeTest.java +++ b/basex-core/src/test/java/org/basex/query/SeqTypeTest.java @@ -1,6 +1,7 @@ package org.basex.query; import static org.basex.query.value.type.BasicType.*; +import static org.basex.query.value.type.ListType.*; import static org.basex.query.value.type.NodeType.*; import static org.basex.query.value.type.Occ.*; import static org.basex.query.value.type.Types.*; @@ -283,17 +284,19 @@ private static void compute(final Occ[][] table, final BiFunction final SeqType // (xs:date | xs:string) - c1 = SeqType.get(ChoiceItemType.get(DATE_O, STRING_O), EXACTLY_ONE), + c1 = SeqType.get(ChoiceItemType.get(DATE, STRING), EXACTLY_ONE), // (element() | xs:string) - c2 = SeqType.get(ChoiceItemType.get(ELEMENT_O, STRING_O), EXACTLY_ONE), + c2 = SeqType.get(ChoiceItemType.get(ELEMENT, STRING), EXACTLY_ONE), // (xs:NMTOKENS | xs:string) - c3 = SeqType.get(ChoiceItemType.get(NMTOKENS_O, STRING_O), EXACTLY_ONE), + c3 = SeqType.get(ChoiceItemType.get(NMTOKENS, STRING), EXACTLY_ONE), // (array(*) | xs:string) - c4 = SeqType.get(ChoiceItemType.get(ARRAY_O, STRING_O), EXACTLY_ONE), + c4 = SeqType.get(ChoiceItemType.get(ARRAY, STRING), EXACTLY_ONE), // (map(*) | xs:string) - c5 = SeqType.get(ChoiceItemType.get(MAP_O, STRING_O), EXACTLY_ONE), + c5 = SeqType.get(ChoiceItemType.get(MAP, STRING), EXACTLY_ONE), // (function(*) | xs:string) - c6 = SeqType.get(ChoiceItemType.get(FUNCTION_O, STRING_O), EXACTLY_ONE); + c6 = SeqType.get(ChoiceItemType.get(FUNCTION, STRING), EXACTLY_ONE), + // (node() | jnode()) + c7 = SeqType.get(ChoiceItemType.get(NODE, JNODE), EXACTLY_ONE); assertTrue(c1.instanceOf(c1)); assertFalse(c1.instanceOf(c2)); @@ -355,6 +358,14 @@ private static void compute(final Occ[][] table, final BiFunction assertTrue(FUNCTION_O.instanceOf(c6)); assertFalse(c6.instanceOf(STRING_O)); assertTrue(STRING_O.instanceOf(c6)); + assertTrue(Types.NUMERIC_EXPANSION.seqType().instanceOf(NUMERIC_O)); + assertTrue(NUMERIC_O.instanceOf(Types.NUMERIC_EXPANSION.seqType())); + assertTrue(Types.ANY_ATOMIC_TYPE_EXPANSION.seqType().instanceOf(ANY_ATOMIC_TYPE_O)); + assertTrue(ANY_ATOMIC_TYPE_O.instanceOf(Types.ANY_ATOMIC_TYPE_EXPANSION.seqType())); + assertTrue(Types.ITEM_EXPANSION.seqType().instanceOf(ITEM_O)); + assertTrue(ITEM_O.instanceOf(Types.ITEM_EXPANSION.seqType())); + assertTrue(c7.instanceOf(GNODE_O)); + assertTrue(GNODE_O.instanceOf(c7)); final TokenObjectMap fld1 = new TokenObjectMap<>(), fld2 = new TokenObjectMap<>(); final QNm r1Name = new QNm(Token.token("r1")), r2Name = new QNm(Token.token("r2")); @@ -550,17 +561,17 @@ private static void compute(final Occ[][] table, final BiFunction final SeqType // (xs:date | xs:string) - c1 = SeqType.get(ChoiceItemType.get(DATE_O, STRING_O), EXACTLY_ONE), + c1 = SeqType.get(ChoiceItemType.get(DATE, STRING), EXACTLY_ONE), // (element() | xs:string) - c2 = SeqType.get(ChoiceItemType.get(ELEMENT_O, STRING_O), EXACTLY_ONE), + c2 = SeqType.get(ChoiceItemType.get(ELEMENT, STRING), EXACTLY_ONE), // (xs:NMTOKENS | xs:string) - c3 = SeqType.get(ChoiceItemType.get(NMTOKENS_O, STRING_O), EXACTLY_ONE), + c3 = SeqType.get(ChoiceItemType.get(NMTOKENS, STRING), EXACTLY_ONE), // (array(*) | xs:string) - c4 = SeqType.get(ChoiceItemType.get(ARRAY_O, STRING_O), EXACTLY_ONE), + c4 = SeqType.get(ChoiceItemType.get(ARRAY, STRING), EXACTLY_ONE), // (map(*) | xs:string) - c5 = SeqType.get(ChoiceItemType.get(MAP_O, STRING_O), EXACTLY_ONE), + c5 = SeqType.get(ChoiceItemType.get(MAP, STRING), EXACTLY_ONE), // (function(*) | xs:string) - c6 = SeqType.get(ChoiceItemType.get(FUNCTION_O, STRING_O), EXACTLY_ONE); + c6 = SeqType.get(ChoiceItemType.get(FUNCTION, STRING), EXACTLY_ONE); combine(c1, op); combine(c1, DATE_O, ANY_ATOMIC_TYPE_O, op); @@ -831,17 +842,17 @@ private static void compute(final Occ[][] table, final BiFunction final SeqType // (xs:date | xs:string) - c1 = SeqType.get(ChoiceItemType.get(DATE_O, STRING_O), EXACTLY_ONE), + c1 = SeqType.get(ChoiceItemType.get(DATE, STRING), EXACTLY_ONE), // (element() | xs:string) - c2 = SeqType.get(ChoiceItemType.get(ELEMENT_O, STRING_O), EXACTLY_ONE), + c2 = SeqType.get(ChoiceItemType.get(ELEMENT, STRING), EXACTLY_ONE), // (xs:NMTOKENS | xs:string) - c3 = SeqType.get(ChoiceItemType.get(NMTOKENS_O, STRING_O), EXACTLY_ONE), + c3 = SeqType.get(ChoiceItemType.get(NMTOKENS, STRING), EXACTLY_ONE), // (array(*) | xs:string) - c4 = SeqType.get(ChoiceItemType.get(ARRAY_O, STRING_O), EXACTLY_ONE), + c4 = SeqType.get(ChoiceItemType.get(ARRAY, STRING), EXACTLY_ONE), // (map(*) | xs:string) - c5 = SeqType.get(ChoiceItemType.get(MAP_O, STRING_O), EXACTLY_ONE), + c5 = SeqType.get(ChoiceItemType.get(MAP, STRING), EXACTLY_ONE), // (function(*) | xs:string) - c6 = SeqType.get(ChoiceItemType.get(FUNCTION_O, STRING_O), EXACTLY_ONE); + c6 = SeqType.get(ChoiceItemType.get(FUNCTION, STRING), EXACTLY_ONE); combine(c1, op); combine(c1, DATE_O, DATE_O, op);