package client.net.sf.saxon.ce.type;
import client.net.sf.saxon.ce.Configuration;
import client.net.sf.saxon.ce.om.*;
import client.net.sf.saxon.ce.value.*;
/**
* This class represents a built-in atomic type, which may be either a primitive type
* (such as xs:decimal or xs:anyURI) or a derived type (such as xs:ID or xs:dayTimeDuration).
*/
public class BuiltInAtomicType implements AtomicType {
int fingerprint;
int baseFingerprint;
int primitiveFingerprint;
boolean ordered = false;
public static BuiltInAtomicType ANY_ATOMIC = makeAtomicType(StandardNames.XS_ANY_ATOMIC_TYPE, AnySimpleType.getInstance(), true);
public static BuiltInAtomicType NUMERIC = makeAtomicType(StandardNames.XS_NUMERIC, ANY_ATOMIC, true);
public static BuiltInAtomicType STRING = makeAtomicType(StandardNames.XS_STRING, ANY_ATOMIC, true);
public static BuiltInAtomicType BOOLEAN = makeAtomicType(StandardNames.XS_BOOLEAN, ANY_ATOMIC, true);
public static BuiltInAtomicType DURATION = makeAtomicType(StandardNames.XS_DURATION, ANY_ATOMIC, false);
public static BuiltInAtomicType DATE_TIME = makeAtomicType(StandardNames.XS_DATE_TIME, ANY_ATOMIC, true);
public static BuiltInAtomicType DATE = makeAtomicType(StandardNames.XS_DATE, ANY_ATOMIC, true);
public static BuiltInAtomicType TIME = makeAtomicType(StandardNames.XS_TIME, ANY_ATOMIC, true);
public static BuiltInAtomicType G_YEAR_MONTH = makeAtomicType(StandardNames.XS_G_YEAR_MONTH, ANY_ATOMIC, false);
public static BuiltInAtomicType G_MONTH = makeAtomicType(StandardNames.XS_G_MONTH, ANY_ATOMIC, false);
public static BuiltInAtomicType G_MONTH_DAY = makeAtomicType(StandardNames.XS_G_MONTH_DAY, ANY_ATOMIC, false);
public static BuiltInAtomicType G_YEAR = makeAtomicType(StandardNames.XS_G_YEAR, ANY_ATOMIC, false);
public static BuiltInAtomicType G_DAY = makeAtomicType(StandardNames.XS_G_DAY, ANY_ATOMIC, false);
public static BuiltInAtomicType HEX_BINARY = makeAtomicType(StandardNames.XS_HEX_BINARY, ANY_ATOMIC, false);
public static BuiltInAtomicType BASE64_BINARY = makeAtomicType(StandardNames.XS_BASE64_BINARY, ANY_ATOMIC, false);
public static BuiltInAtomicType ANY_URI = makeAtomicType(StandardNames.XS_ANY_URI, ANY_ATOMIC, true);
public static BuiltInAtomicType QNAME = makeAtomicType(StandardNames.XS_QNAME, ANY_ATOMIC, false);
public static BuiltInAtomicType UNTYPED_ATOMIC = makeAtomicType(StandardNames.XS_UNTYPED_ATOMIC, ANY_ATOMIC, true);
public static BuiltInAtomicType DECIMAL = makeAtomicType(StandardNames.XS_DECIMAL, NUMERIC, true);
public static BuiltInAtomicType FLOAT = makeAtomicType(StandardNames.XS_FLOAT, NUMERIC, true);
public static BuiltInAtomicType DOUBLE = makeAtomicType(StandardNames.XS_DOUBLE, NUMERIC, true);
public static BuiltInAtomicType INTEGER = makeAtomicType(StandardNames.XS_INTEGER, DECIMAL, true);
public static BuiltInAtomicType YEAR_MONTH_DURATION = makeAtomicType(StandardNames.XS_YEAR_MONTH_DURATION, DURATION, true);
public static BuiltInAtomicType DAY_TIME_DURATION = makeAtomicType(StandardNames.XS_DAY_TIME_DURATION, DURATION, true);
//public static BuiltInAtomicType ID = makeAtomicType(StandardNames.XS_ID, STRING, true);
//public static BuiltInAtomicType LANGUAGE = makeAtomicType(StandardNames.XS_LANGUAGE, STRING, true);
//public static BuiltInAtomicType IDREF = makeAtomicType(StandardNames.XS_IDREF, STRING, true);
static {
}
private BuiltInAtomicType(int fingerprint) {
this.fingerprint = fingerprint;
}
/**
* Determine whether the atomic type is ordered, that is, whether less-than and greater-than comparisons
* are permitted
*
* @return true if ordering operations are permitted
*/
public boolean isOrdered() {
return ordered;
}
/**
* Determine whether the atomic type is numeric
*
* @return true if the type is a built-in numeric type
*/
public boolean isPrimitiveNumeric() {
switch (fingerprint) {
case StandardNames.XS_INTEGER:
case StandardNames.XS_DECIMAL:
case StandardNames.XS_DOUBLE:
case StandardNames.XS_FLOAT:
case StandardNames.XS_NUMERIC:
return true;
default:
return false;
}
}
/**
* Set the base type of this type
*
* @param baseFingerprint the namepool fingerprint of the name of the base type
*/
public final void setBaseTypeFingerprint(int baseFingerprint) {
this.baseFingerprint = baseFingerprint;
}
/**
* Get the fingerprint of the name of this type
*
* @return the fingerprint. Returns an invented fingerprint for an anonymous type.
*/
public int getFingerprint() {
return fingerprint;
}
/**
* Get the display name of the type: that is, a lexical QName with an arbitrary prefix
*
* @return a lexical QName identifying the type
*/
public String getDisplayName() {
if (fingerprint == StandardNames.XS_NUMERIC) {
return "numeric";
} else {
return StandardNames.getDisplayName(fingerprint);
}
}
/**
* Determine whether the atomic type is a primitive type. The primitive types are
* the 19 primitive types of XML Schema, plus xs:integer, xs:dayTimeDuration and xs:yearMonthDuration;
* xs:untypedAtomic; and all supertypes of these (xs:anyAtomicType, xs:numeric, ...)
*
* @return true if the type is considered primitive under the above rules
*/
public boolean isPrimitiveType() {
return Type.isPrimitiveType(fingerprint);
}
/**
* Returns the base type that this type inherits from. This method can be used to get the
* base type of a type that is known to be valid.
* If this type is a Simpletype that is a built in primitive type then null is returned.
*
* @return the base type.
* @throws IllegalStateException if this type is not valid.
*/
public final SchemaType getBaseType() {
if (baseFingerprint == -1) {
return null;
} else {
return BuiltInType.getSchemaType(baseFingerprint);
}
}
/**
* Test whether a given item conforms to this type
*
* @param item The item to be tested
* @param allowURIPromotion true if we regard a URI as effectively a subtype of String
* @param config the Saxon configuration (used to locate the type hierarchy cache)
* @return true if the item is an instance of this type; false otherwise
*/
public boolean matchesItem(Item item, boolean allowURIPromotion, Configuration config) {
if (item instanceof AtomicValue) {
AtomicValue value = (AtomicValue)item;
// Try to match primitive types first
if (value.getPrimitiveType() == this) {
return true;
}
AtomicType type = value.getTypeLabel();
if (type.getFingerprint() == getFingerprint()) {
// note, with compiled stylesheets one can have two objects representing
// the same type, so comparing identity is not safe
return true;
}
final TypeHierarchy th = config.getTypeHierarchy();
boolean ok = th.isSubType(type, this);
if (ok) {
return true;
}
if (allowURIPromotion && getFingerprint() == StandardNames.XS_STRING && th.isSubType(type, BuiltInAtomicType.ANY_URI)) {
// allow promotion from anyURI to string
return true;
}
}
return false;
}
/**
* Get the type from which this item type is derived by restriction. This
* is the supertype in the XPath type heirarchy, as distinct from the Schema
* base type: this means that the supertype of xs:boolean is xs:anyAtomicType,
* whose supertype is item() (rather than xs:anySimpleType).
*
* @param th the type hierarchy cache, not used in this implementation
* @return the supertype, or null if this type is item()
*/
public ItemType getSuperType(TypeHierarchy th) {
SchemaType base = getBaseType();
if (base instanceof AnySimpleType) {
return AnyItemType.getInstance();
} else {
return (ItemType)base;
}
}
/**
* Get the primitive item type corresponding to this item type. For item(),
* this is Type.ITEM. For node(), it is Type.NODE. For specific node kinds,
* it is the value representing the node kind, for example Type.ELEMENT.
* For anyAtomicValue it is Type.ATOMIC_VALUE. For numeric it is Type.NUMBER.
* For other atomic types it is the primitive type as defined in XML Schema,
* except that INTEGER is considered to be a primitive type.
*/
public ItemType getPrimitiveItemType() {
return this; // all atomic types in Saxon-CE are primitive
}
/**
* Get the primitive type corresponding to this item type. For item(),
* this is Type.ITEM. For node(), it is Type.NODE. For specific node kinds,
* it is the value representing the node kind, for example Type.ELEMENT.
* For anyAtomicValue it is Type.ATOMIC_VALUE. For numeric it is Type.NUMBER.
* For other atomic types it is the primitive type as defined in XML Schema,
* except that INTEGER is considered to be a primitive type.
*/
public int getPrimitiveType() {
return primitiveFingerprint;
}
/**
* Produce a representation of this type name for use in error messages.
* Where this is a QName, it will use conventional prefixes
*/
public String toString(NamePool pool) {
return getDisplayName();
}
/**
* Get the item type of the atomic values that will be produced when an item
* of this type is atomized
*/
public AtomicType getAtomizedItemType() {
return this;
}
/**
* Test whether this is the same type as another type. They are considered to be the same type
* if they are derived from the same type definition in the original XML representation (which
* can happen when there are multiple includes of the same file)
*/
public boolean isSameType(SchemaType other) {
return other.getFingerprint() == getFingerprint();
}
public String toString() {
return getDisplayName();
}
/**
* Test whether this Simple Type is an atomic type
*
* @return true, this is an atomic type
*/
public boolean isAtomicType() {
return true;
}
/**
* Ask whether this type is an ID type. This is defined to be any simple type
* who typed value may contain atomic values of type xs:ID: that is, it includes types derived
* from ID by restriction, list, or union. Note that for a node to be treated
* as an ID, its typed value must be a *single* atomic value of type ID; the type of the
* node, however, can still allow a list.
*/
public boolean isIdType() {
return fingerprint == StandardNames.XS_ID;
}
/**
* Ask whether this type is an IDREF or IDREFS type. This is defined to be any simple type
* who typed value may contain atomic values of type xs:IDREF: that is, it includes types derived
* from IDREF or IDREFS by restriction, list, or union
*/
public boolean isIdRefType() {
return fingerprint == StandardNames.XS_IDREF;
}
/**
* Test whether this simple type is namespace-sensitive, that is, whether
* it is derived from xs:QName or xs:NOTATION
*
* @return true if this type is derived from xs:QName or xs:NOTATION
*/
public boolean isNamespaceSensitive() {
return getFingerprint() == StandardNames.XS_QNAME;
}
/**
* Two types are equal if they have the same fingerprint.
* Note: it is normally safe to use ==, because we always use the static constants, one instance
* for each built in atomic type. However, after serialization and deserialization a different instance
* can appear.
*/
public boolean equals(Object obj) {
return obj instanceof BuiltInAtomicType &&
getFingerprint() == ((BuiltInAtomicType)obj).getFingerprint();
}
/**
* The fingerprint can be used as a hashcode
*/
public int hashCode() {
return getFingerprint();
}
/**
* Internal factory method to create a BuiltInAtomicType. There is one instance for each of the
* built-in atomic types
*
* @param fingerprint The name of the type
* @param baseType The base type from which this type is derived
* @return the newly constructed built in atomic type
*/
private static BuiltInAtomicType makeAtomicType(int fingerprint, SchemaType baseType, boolean ordered) {
BuiltInAtomicType t = new BuiltInAtomicType(fingerprint);
t.setBaseTypeFingerprint(baseType.getFingerprint());
if (t.isPrimitiveType()) {
t.primitiveFingerprint = fingerprint;
} else {
t.primitiveFingerprint = ((AtomicType)baseType).getPrimitiveType();
}
t.ordered = ordered;
BuiltInType.register(fingerprint, t);
return t;
}
}
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is “Incompatible With Secondary Licenses”, as defined by the Mozilla Public License, v. 2.0.