KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > type > Type


1 package net.sf.saxon.type;
2 import net.sf.saxon.om.Item;
3 import net.sf.saxon.om.NamePool;
4 import net.sf.saxon.om.NodeInfo;
5 import net.sf.saxon.pattern.AnyNodeTest;
6 import net.sf.saxon.pattern.DocumentNodeTest;
7 import net.sf.saxon.pattern.NoNodeTest;
8 import net.sf.saxon.pattern.NodeTest;
9 import net.sf.saxon.style.StandardNames;
10 import net.sf.saxon.value.AtomicValue;
11
12 import java.io.Serializable JavaDoc;
13 import java.util.Set JavaDoc;
14
15
16 /**
17  * This class contains static information about types and methods for constructing type codes.
18  * The class is never instantiated.
19  *
20  */

21
22 public abstract class Type implements Serializable JavaDoc {
23
24     // Note that the integer codes representing node kinds are the same as
25
// the codes allocated in the DOM interface, while the codes for built-in
26
// atomic type are fingerprints allocated in StandardNames. These two sets of
27
// codes must not overlap!
28

29     // The constants that are defined as synonyms of constants in StandardNames
30
// are purely for convenience (or for legacy), they will eventually be phased out.
31

32     /**
33      * Type representing an element node - element()
34      */

35
36     public static final short ELEMENT = 1;
37     /**
38      * Item type representing an attribute node - attribute()
39      */

40     public static final short ATTRIBUTE = 2;
41     /**
42      * Item type representing a text node - text()
43      */

44     public static final short TEXT = 3;
45     /**
46      * Item type representing a processing-instruction node
47      */

48     public static final short PROCESSING_INSTRUCTION = 7;
49     /**
50      * Item type representing a comment node
51      */

52     public static final short COMMENT = 8;
53     /**
54      * Item type representing a document node
55      */

56     public static final short DOCUMENT = 9;
57     /**
58      * Item type representing a namespace node
59      */

60     public static final short NAMESPACE = 13;
61     /**
62      * Dummy node kind used in the tiny tree to mark the end of the tree
63      */

64     public static final short STOPPER = 11;
65     /**
66      * Dummy node kind used in the tiny tree to contain a parent pointer
67      */

68     public static final short PARENT_POINTER = 12;
69
70     /**
71      * An item type that matches any node
72      */

73
74     public static final short NODE = 0;
75
76     public static final ItemType NODE_TYPE = AnyNodeTest.getInstance();
77
78     /**
79      * An item type that matches any item
80      */

81
82     public static final short ITEM = 88;
83
84     public static final ItemType ITEM_TYPE = AnyItemType.getInstance();
85
86
87
88     /**
89      * A type that matches nothing
90      */

91
92     public static final short MAX_NODE_TYPE = 13;
93     /**
94      * Item type that matches no items (corresponds to SequenceType empty())
95      */

96     public static final short EMPTY = 15; // a test for this type will never be satisfied
97

98     private Type() {
99     }
100
101     /**
102      * Test whether a given type is (some subtype of) node()
103      *
104      * @param type The type to be tested
105      * @return true if the item type is node() or a subtype of node()
106      */

107
108     public static boolean isNodeType(ItemType type) {
109         return type instanceof NodeTest;
110     }
111
112     /**
113      * Constant denoting any atomic type (the union of all primitive types and types
114      * derived from primitive types by restriction or by union)
115      */

116
117     //public static final int ATOMIC = 90;
118
public static final int ATOMIC = StandardNames.XDT_ANY_ATOMIC_TYPE;
119
120     /**
121      * Constant denoting any numeric type (the union of float, double, and decimal)
122      */

123
124     //public static final int NUMBER = 91;
125
public static final int NUMBER = StandardNames.XDT_NUMERIC;
126
127     /**
128      * Constants representing primitive data types defined in Schema Part 2
129      */

130
131     public static final int STRING = StandardNames.XS_STRING;
132     /**
133      * Item type representing the type xs:boolean
134      */

135     public static final int BOOLEAN = StandardNames.XS_BOOLEAN;
136     /**
137      * Item type representing the type xs:decimal
138      */

139     public static final int DECIMAL = StandardNames.XS_DECIMAL;
140     /**
141      * Item type representing the type xs:float
142      */

143     public static final int FLOAT = StandardNames.XS_FLOAT;
144     /**
145      * Item type representing the type xs:double
146      */

147     public static final int DOUBLE = StandardNames.XS_DOUBLE;
148     /**
149      * Item type representing the type xs:duration
150      */

151     public static final int DURATION = StandardNames.XS_DURATION;
152     /**
153      * Item type representing the type xs:dateTime
154      */

155     public static final int DATE_TIME = StandardNames.XS_DATE_TIME;
156     /**
157      * Item type representing the type xs:time
158      */

159     public static final int TIME = StandardNames.XS_TIME;
160     /**
161      * Item type representing the type xs:date
162      */

163     public static final int DATE = StandardNames.XS_DATE;
164     /**
165      * Item type representing the type xs:gYearMonth
166      */

167     public static final int G_YEAR_MONTH = StandardNames.XS_G_YEAR_MONTH;
168     /**
169      * Item type representing the type xs:gYear
170      */

171     public static final int G_YEAR = StandardNames.XS_G_YEAR;
172     /**
173      * Item type representing the type xs:monthDay
174      */

175     public static final int G_MONTH_DAY = StandardNames.XS_G_MONTH_DAY;
176     /**
177      * Item type representing the type xs:gDay
178      */

179     public static final int G_DAY = StandardNames.XS_G_DAY;
180     /**
181      * Item type representing the type xs:gMonth
182      */

183     public static final int G_MONTH = StandardNames.XS_G_MONTH;
184     /**
185      * Item type representing the type xs:hexBinary
186      */

187     public static final int HEX_BINARY = StandardNames.XS_HEX_BINARY;
188     /**
189      * Item type representing the type xs:base64Binary
190      */

191     public static final int BASE64_BINARY = StandardNames.XS_BASE64_BINARY;
192     /**
193      * Item type representing the type xs:anyURI
194      */

195     public static final int ANY_URI = StandardNames.XS_ANY_URI;
196     /**
197      * Item type representing the type xs:QName
198      */

199     public static final int QNAME = StandardNames.XS_QNAME;
200     /**
201      * Item type representing the type xs:NOTATION
202      *
203      */

204     public static final int NOTATION = StandardNames.XS_NOTATION;
205
206     /**
207      * Item type representing the type xdt:untypedAtomic
208      * (the type of the content of a schema-less node)
209      */

210
211     public static final int UNTYPED_ATOMIC = StandardNames.XDT_UNTYPED_ATOMIC;
212
213     public static final int ANY_SIMPLE_TYPE = StandardNames.XS_ANY_SIMPLE_TYPE;
214
215     /**
216      * Constant representing the type of an external object (for use by extension functions)
217      */

218
219     public static final int OBJECT = StandardNames.SAXON_JAVA_LANG_OBJECT;
220
221     /**
222      * Item type representing the type xs:integer
223      */

224
225     public static final int INTEGER = StandardNames.XS_INTEGER;
226     /**
227      * Item type representing the type xs:nonPositiveInteger
228      */

229     public static final int NON_POSITIVE_INTEGER = StandardNames.XS_NON_POSITIVE_INTEGER;
230     /**
231      * Item type representing the type xs:negativeInteger
232      */

233     public static final int NEGATIVE_INTEGER = StandardNames.XS_NEGATIVE_INTEGER;
234     /**
235      * Item type representing the type xs:long
236      */

237     public static final int LONG = StandardNames.XS_LONG;
238     /**
239      * Item type representing the type xs:int
240      */

241     public static final int INT = StandardNames.XS_INT;
242     /**
243      * Item type representing the type xs:short
244      */

245     public static final int SHORT = StandardNames.XS_SHORT;
246     /**
247      * Item type representing the type xs:byte
248      */

249     public static final int BYTE = StandardNames.XS_BYTE;
250     /**
251      * Item type representing the type xs:nonNegativeInteger
252      */

253     public static final int NON_NEGATIVE_INTEGER = StandardNames.XS_NON_NEGATIVE_INTEGER;
254     /**
255      * Item type representing the type xs:positiveInteger
256      */

257     public static final int POSITIVE_INTEGER = StandardNames.XS_POSITIVE_INTEGER;
258     /**
259      * Item type representing the type xs:unsignedLong
260      */

261     public static final int UNSIGNED_LONG = StandardNames.XS_UNSIGNED_LONG;
262     /**
263      * Item type representing the type xs:unsignedInt
264      */

265     public static final int UNSIGNED_INT = StandardNames.XS_UNSIGNED_INT;
266     /**
267      * Item type representing the type xs:unsignedShort
268      */

269     public static final int UNSIGNED_SHORT = StandardNames.XS_UNSIGNED_SHORT;
270     /**
271      * Item type representing the type xs:unsignedByte
272      */

273     public static final int UNSIGNED_BYTE = StandardNames.XS_UNSIGNED_BYTE;
274
275     /**
276      * Item type representing the type xs:normalizedString
277      */

278     public static final int NORMALIZED_STRING = StandardNames.XS_NORMALIZED_STRING;
279     /**
280      * Item type representing the type xs:token
281      */

282     public static final int TOKEN = StandardNames.XS_TOKEN;
283     /**
284      * Item type representing the type xs:language
285      */

286     public static final int LANGUAGE = StandardNames.XS_LANGUAGE;
287     /**
288      * Item type representing the type xs:NMTOKEN
289      */

290     public static final int NMTOKEN = StandardNames.XS_NMTOKEN;
291     /**
292      * Content type representing the complex type xs:NMTOKENS
293      */

294     public static final int NMTOKENS = StandardNames.XS_NMTOKENS; // NB: list type
295
/**
296      * Item type representing the type xs:NAME
297      */

298     public static final int NAME = StandardNames.XS_NAME;
299     /**
300      * Item type representing the type xs:NCNAME
301      */

302     public static final int NCNAME = StandardNames.XS_NCNAME;
303     /**
304      * Item type representing the type xs:ID
305      */

306     public static final int ID = StandardNames.XS_ID;
307     /**
308      * Item type representing the type xs:IDREF
309      */

310     public static final int IDREF = StandardNames.XS_IDREF;
311     /**
312      * Content type representing the complex type xs:IDREFS
313      */

314     public static final int IDREFS = StandardNames.XS_IDREFS; // NB: list type
315
/**
316      *
317      * Item type representing the type xs:ENTITY
318      */

319     public static final int ENTITY = StandardNames.XS_ENTITY;
320
321     /**
322      *
323      * Item type representing the type xdt:yearMonthDuration
324      */

325     public static final int YEAR_MONTH_DURATION = StandardNames.XDT_YEAR_MONTH_DURATION;
326     /**
327      *
328      * Item type representing the type xdt:dayTimeDuration
329      */

330     public static final int DAY_TIME_DURATION = StandardNames.XDT_DAY_TIME_DURATION;
331
332     public static final BuiltInAtomicType UNTYPED_ATOMIC_TYPE = (BuiltInAtomicType)
333         BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_UNTYPED_ATOMIC);
334
335     public static final BuiltInAtomicType ANY_ATOMIC_TYPE = (BuiltInAtomicType)
336         BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_ANY_ATOMIC_TYPE);
337
338     public static final BuiltInAtomicType YEAR_MONTH_DURATION_TYPE = (BuiltInAtomicType)
339         BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_YEAR_MONTH_DURATION);
340
341     public static final BuiltInAtomicType DAY_TIME_DURATION_TYPE = (BuiltInAtomicType)
342         BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_DAY_TIME_DURATION);
343
344     public static final BuiltInAtomicType STRING_TYPE = (BuiltInAtomicType)
345         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_STRING);
346
347     public static final BuiltInAtomicType BOOLEAN_TYPE = (BuiltInAtomicType)
348         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_BOOLEAN);
349
350     public static final BuiltInAtomicType DECIMAL_TYPE = (BuiltInAtomicType)
351         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_DECIMAL);
352
353     public static final BuiltInAtomicType FLOAT_TYPE = (BuiltInAtomicType)
354         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_FLOAT);
355
356     public static final BuiltInAtomicType DOUBLE_TYPE = (BuiltInAtomicType)
357         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_DOUBLE);
358
359     public static final BuiltInAtomicType DURATION_TYPE = (BuiltInAtomicType)
360         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_DURATION);
361
362     public static final BuiltInAtomicType DATE_TIME_TYPE = (BuiltInAtomicType)
363         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_DATE_TIME);
364
365     public static final BuiltInAtomicType TIME_TYPE = (BuiltInAtomicType)
366         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_TIME);
367
368     public static final BuiltInAtomicType DATE_TYPE = (BuiltInAtomicType)
369         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_DATE);
370
371     public static final BuiltInAtomicType G_YEAR_MONTH_TYPE = (BuiltInAtomicType)
372         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_G_YEAR_MONTH);
373
374     public static final BuiltInAtomicType G_YEAR_TYPE = (BuiltInAtomicType)
375         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_G_YEAR);
376
377     public static final BuiltInAtomicType G_MONTH_DAY_TYPE = (BuiltInAtomicType)
378         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_G_MONTH_DAY);
379
380     public static final BuiltInAtomicType G_DAY_TYPE = (BuiltInAtomicType)
381         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_G_DAY);
382
383     public static final BuiltInAtomicType G_MONTH_TYPE = (BuiltInAtomicType)
384         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_G_MONTH);
385
386     public static final BuiltInAtomicType HEX_BINARY_TYPE = (BuiltInAtomicType)
387         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_HEX_BINARY);
388
389     public static final BuiltInAtomicType BASE64_BINARY_TYPE = (BuiltInAtomicType)
390         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_BASE64_BINARY);
391
392     public static final BuiltInAtomicType ANY_URI_TYPE = (BuiltInAtomicType)
393         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_ANY_URI);
394
395     public static final BuiltInAtomicType QNAME_TYPE = (BuiltInAtomicType)
396         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_QNAME);
397
398     public static final BuiltInAtomicType NOTATION_TYPE = (BuiltInAtomicType)
399         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_NOTATION);
400
401     public static final BuiltInAtomicType INTEGER_TYPE = (BuiltInAtomicType)
402         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_INTEGER);
403
404     public static final BuiltInAtomicType ID_TYPE = (BuiltInAtomicType)
405         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_ID);
406
407     public static final BuiltInAtomicType NCNAME_TYPE = (BuiltInAtomicType)
408         BuiltInSchemaFactory.getSchemaType(StandardNames.XS_NCNAME);
409
410     public static final BuiltInAtomicType NUMBER_TYPE = (BuiltInAtomicType)
411         BuiltInSchemaFactory.getSchemaType(StandardNames.XDT_NUMERIC);
412             // TODO: actually, the number type is anonymous?
413

414     /**
415      * Output (for diagnostics) a representation of the type of an item. This
416      * does not have to be the most specific type
417      */

418
419     public static final String JavaDoc displayTypeName(Item item) {
420         if (item instanceof NodeInfo) {
421             NodeInfo node = (NodeInfo)item;
422             switch (node.getNodeKind()) {
423                 case DOCUMENT:
424                     return "document-node()";
425                 case ELEMENT:
426                     NamePool pool = node.getNamePool();
427                     int annotation = node.getTypeAnnotation();
428                     return "element(" +
429                             ((NodeInfo)item).getDisplayName() + ", " +
430                             (annotation == -1 ?
431                                 "xdt:untyped)" :
432                                 pool.getDisplayName(annotation) + ')');
433                 case ATTRIBUTE:
434                     NamePool pool2 = node.getNamePool();
435                     int annotation2 = node.getTypeAnnotation() & NamePool.FP_MASK;
436                     return "attribute(" +
437                             ((NodeInfo)item).getDisplayName()+ ", " +
438                             (annotation2 == -1 ?
439                                 "xdt:untypedAtomic)" :
440                                 pool2.getDisplayName(annotation2) + ')');
441                 case TEXT: return "text()";
442                 case COMMENT: return "comment()";
443                 case PROCESSING_INSTRUCTION:
444                                 return "processing-instruction()";
445                 case NAMESPACE: return "namespace()";
446                 default: return "";
447             }
448         } else {
449             return ((AtomicValue)item).getItemType().toString();
450         }
451     }
452
453     /**
454      * Get the SimpleType object for a built-in simple type code
455      * @return the SimpleType, or null if not found
456      */

457
458     public static ItemType getBuiltInItemType(String JavaDoc namespace, String JavaDoc localName) {
459         SchemaType t = BuiltInSchemaFactory.getSchemaType(
460                 StandardNames.getFingerprint(namespace, localName));
461         if (t instanceof ItemType) {
462             return (ItemType)t;
463         } else {
464             return null;
465         }
466     }
467
468     /**
469      * Determine whether type A is type B or one of its subtypes, recursively
470      *
471      * @param subtype identifies the first type
472      * @param supertype identifies the second type
473      * @return true if the first type is the second type or a (direct or
474      * indirect) subtype of the second type
475      */

476
477     public static boolean isSubType(ItemType subtype, ItemType supertype) {
478         int relation = relationship(subtype, supertype);
479         return (relation==SAME_TYPE || relation==SUBSUMED_BY);
480     }
481
482     /**
483      * Constant denoting relationship between two types: A is the same type as B
484      */

485     public static final int SAME_TYPE = 0;
486
487     /**
488      * Constant denoting relationship between two types: A subsumes B
489      */

490     public static final int SUBSUMES = 1;
491
492     /**
493      * Constant denoting relationship between two types: A is subsumed by B
494      */

495     public static final int SUBSUMED_BY = 2;
496
497     /**
498      * Constant denoting relationship between two types: A overlaps B
499      */

500     public static final int OVERLAPS = 3;
501
502     /**
503      * Constant denoting relationship between two types: A is disjoint from B
504      */

505     public static final int DISJOINT = 4;
506
507     /**
508      * Determine the relationship of one item type to another.
509      * @param t1 the first item type
510      * @param t2 the second item type
511      * @return {@link #SAME_TYPE} if the types are the same; {@link #SUBSUMES} if the first
512      * type subsumes the second (that is, all instances of the second type are also instances
513      * of the first); {@link #SUBSUMED_BY} if the second type subsumes the first;
514      * {@link #OVERLAPS} if the two types overlap (have a non-empty intersection, but neither
515      * subsumes the other); {@link #DISJOINT} if the two types are disjoint (have an empty intersection)
516      */

517
518     public static int relationship(ItemType t1, ItemType t2) {
519         // TODO: cache the results of this function to avoid expensive re-computation
520
if (t1 == t2) {
521             return SAME_TYPE;
522         }
523         if (t1 instanceof AnyItemType) {
524             if (t2 instanceof AnyItemType) {
525                 return SAME_TYPE;
526             } else {
527                 return SUBSUMES;
528             }
529         } else if (t2 instanceof AnyItemType) {
530             return SUBSUMED_BY;
531         } else if (t1 instanceof AtomicType) {
532             if (t2 instanceof NodeTest) {
533                 return DISJOINT;
534             } else {
535                 if (((AtomicType)t1).getFingerprint() == ((AtomicType)t2).getFingerprint()) {
536                     return SAME_TYPE;
537                 }
538                 ItemType t = t2;
539                 while (t instanceof AtomicType) {
540                     if (((AtomicType)t1).getFingerprint() == ((AtomicType)t).getFingerprint()) {
541                         return SUBSUMES;
542                     }
543                     t = t.getSuperType();
544                 }
545                 t = t1;
546                 while (t instanceof AtomicType) {
547                     if (((AtomicType)t).getFingerprint() == ((AtomicType)t2).getFingerprint()) {
548                         return SUBSUMED_BY;
549                     }
550                     t = t.getSuperType();
551                 }
552                 return DISJOINT;
553             }
554         } else {
555             // t1 is a NodeTest
556
if (t2 instanceof AtomicType) {
557                 return DISJOINT;
558             } else {
559                 // both types are NodeTests
560
if (t1 instanceof AnyNodeTest) {
561                     if (t2 instanceof AnyNodeTest) {
562                         return SAME_TYPE;
563                     } else {
564                         return SUBSUMES;
565                     }
566                 } else if (t2 instanceof AnyNodeTest) {
567                     return SUBSUMED_BY;
568                 } else if (t1 instanceof NoNodeTest) {
569                     return DISJOINT;
570                 } else if (t2 instanceof NoNodeTest) {
571                     return DISJOINT;
572                 } else {
573                     // first find the relationship between the node kinds allowed
574
int nodeKindRelationship;
575                     int m1 = ((NodeTest)t1).getNodeKindMask();
576                     int m2 = ((NodeTest)t2).getNodeKindMask();
577                     if ((m1 & m2) == 0) {
578                         return DISJOINT;
579                     } else if (m1 == m2) {
580                         nodeKindRelationship = SAME_TYPE;
581                     } else if ((m1 & m2) == m1) {
582                         nodeKindRelationship = SUBSUMED_BY;
583                     } else if ((m1 & m2) == m2) {
584                         nodeKindRelationship = SUBSUMES;
585                     } else {
586                         nodeKindRelationship = OVERLAPS;
587                     }
588
589                     // now find the relationship between the node names allowed. Note that although
590
// NamespaceTest and LocalNameTest are NodeTests, they do not occur in SequenceTypes,
591
// so we don't need to consider them.
592
int nodeNameRelationship;
593                     Set JavaDoc n1 = ((NodeTest)t1).getRequiredNodeNames(); // null means all names allowed
594
Set JavaDoc n2 = ((NodeTest)t2).getRequiredNodeNames(); // null means all names allowed
595
if (n1 == null) {
596                         if (n2 == null) {
597                             nodeNameRelationship = SAME_TYPE;
598                         } else {
599                             nodeNameRelationship = SUBSUMES;
600                         }
601                     } else if (n2 == null) {
602                         nodeNameRelationship = SUBSUMED_BY;
603                     } else if (n1.containsAll(n2)) {
604                         if (n1.equals(n2)) {
605                             nodeNameRelationship = SAME_TYPE;
606                         } else {
607                             nodeNameRelationship = SUBSUMES;
608                         }
609                     } else if (n2.containsAll(n1)) {
610                         nodeNameRelationship = SUBSUMED_BY;
611                     } else {
612                         n2.retainAll(n1);
613                         if (n2.size() == 0) {
614                             nodeNameRelationship = DISJOINT;
615                         } else {
616                             nodeNameRelationship = OVERLAPS;
617                         }
618                     }
619
620                     // now find the relationship between the content types allowed
621

622                     int contentRelationship;
623
624                     if (t1 instanceof DocumentNodeTest) {
625                         if (t2 instanceof DocumentNodeTest) {
626                             contentRelationship = Type.relationship(((DocumentNodeTest)t1).getElementTest(),
627                                     ((DocumentNodeTest)t2).getElementTest());
628                         } else {
629                             contentRelationship = SUBSUMED_BY;
630                         }
631                     } else if (t2 instanceof DocumentNodeTest) {
632                         contentRelationship = SUBSUMES;
633                     } else {
634                         SchemaType s1 = ((NodeTest)t1).getContentType();
635                         SchemaType s2 = ((NodeTest)t2).getContentType();
636                         contentRelationship = schemaTypeRelationship(s1, s2);
637                     }
638
639                     // now analyse the three different relationsships
640

641                     if (nodeKindRelationship == SAME_TYPE &&
642                             nodeNameRelationship == SAME_TYPE &&
643                             contentRelationship == SAME_TYPE) {
644                         return SAME_TYPE;
645                     } else if ((nodeKindRelationship == SAME_TYPE || nodeKindRelationship == SUBSUMES) &&
646                             (nodeNameRelationship == SAME_TYPE || nodeNameRelationship == SUBSUMES) &&
647                             (contentRelationship == SAME_TYPE || contentRelationship == SUBSUMES)) {
648                         return SUBSUMES;
649                     } else if ((nodeKindRelationship == SAME_TYPE || nodeKindRelationship == SUBSUMED_BY) &&
650                             (nodeNameRelationship == SAME_TYPE || nodeNameRelationship == SUBSUMED_BY) &&
651                             (contentRelationship == SAME_TYPE || contentRelationship == SUBSUMED_BY)) {
652                         return SUBSUMED_BY;
653                     } else if (nodeKindRelationship == DISJOINT ||
654                             nodeNameRelationship == DISJOINT ||
655                             contentRelationship == DISJOINT) {
656                         return DISJOINT;
657                     } else {
658                         return OVERLAPS;
659                     }
660                 }
661             }
662         }
663
664     }
665
666     /**
667      * Get the relationship of two schema types to each other
668      */

669
670     public static int schemaTypeRelationship(SchemaType s1, SchemaType s2) {
671         if (s1.isSameType(s2)) {
672             return SAME_TYPE;
673         }
674         if (s1 instanceof AnyType) {
675             return SUBSUMES;
676         }
677         if (s2 instanceof AnyType) {
678             return SUBSUMED_BY;
679         }
680         SchemaType t1 = s1;
681         while (true) {
682             t1 = t1.getBaseType();
683             if (t1 == null) {
684                 break;
685             }
686             if (t1.isSameType(s2)) {
687                 return SUBSUMED_BY;
688             }
689         }
690         SchemaType t2 = s2;
691         while (true) {
692             t2 = t2.getBaseType();
693             if (t2 == null) {
694                 break;
695             }
696             if (t2.isSameType(s1)) {
697                 return SUBSUMES;
698             }
699         }
700         return DISJOINT;
701     }
702
703     /**
704      * Get a type that is a common supertype of two given types
705      *
706      * @param t1 the first item type
707      * @param t2 the second item type
708      * @return the item type that is a supertype of both
709      * the supplied item types
710      */

711
712     public static final ItemType getCommonSuperType(ItemType t1, ItemType t2) {
713         if (t1 instanceof NoNodeTest) {
714             return t2;
715         }
716         if (t2 instanceof NoNodeTest) {
717             return t1;
718         }
719         int r = Type.relationship(t1, t2);
720         if (r == Type.SAME_TYPE) {
721             return t1;
722         } else if (r == SUBSUMED_BY) {
723             return t2;
724         } else if (r == SUBSUMES) {
725             return t1;
726         } else {
727             return getCommonSuperType(t2.getSuperType(), t1);
728             // eventually we will hit a type that is a supertype of t2. We reverse
729
// the arguments so we go up each branch of the tree alternately.
730
// If we hit the root of the tree, one of the earlier conditions will be satisfied,
731
// so the recursion will stop.
732
}
733     }
734
735     /**
736      * Determine whether this type is a primitive type. The primitive types are
737      * the 19 primitive types of XML Schema, plus xs:integer, xdt:dayTimeDuration and xdt:yearMonthDuration;
738      * xdt:untypedAtomic; the 7 node kinds; and all supertypes of these (item(), node(), xdt:anyAtomicType,
739      * xdt:number, ...)
740      * @param code the item type code to be tested
741      * @return true if the type is considered primitive under the above rules
742      */

743     public static boolean isPrimitiveType(int code) {
744         return code >= 0 && (code <= INTEGER || code == NUMBER ||
745                 code == UNTYPED_ATOMIC || code == ATOMIC ||
746                 code == DAY_TIME_DURATION || code == YEAR_MONTH_DURATION ||
747                 code == StandardNames.XS_ANY_SIMPLE_TYPE);
748     }
749
750     /**
751      * Determine whether two primitive atomic types are comparable
752      * @param t1 the first type to compared.
753      * This must be a primitive atomic type as defined by {@link ItemType#getPrimitiveType}
754      * @param t2 the second type to compared.
755      * This must be a primitive atomic type as defined by {@link ItemType#getPrimitiveType}
756      * @return true if the types are comparable, as defined by the rules of the "eq" operator
757      */

758
759     public static boolean isComparable(int t1, int t2) {
760         if (t1 == ATOMIC || t2 == ATOMIC) return true; // meaning we don't actually know at this stage
761
if (t1 == UNTYPED_ATOMIC) t1 = STRING;
762         if (t2 == UNTYPED_ATOMIC) t2 = STRING;
763         if (t1 == ANY_URI) t1 = STRING;
764         if (t2 == ANY_URI) t2 = STRING;
765         if (t1 == INTEGER || t1 == DOUBLE || t1 == FLOAT || t1 == DECIMAL) t1 = NUMBER;
766         if (t2 == INTEGER || t2 == DOUBLE || t2 == FLOAT || t2 == DECIMAL) t2 = NUMBER;
767         return t1 == t2;
768     }
769
770     /**
771      * Determine whether a primitive type is ordered. Note that the rules for this differ
772      * between XPath and XML Schema: these are the XPath rules.
773      * @param type the primitive item type being tested
774      * @return true if the types are potentially comparable. For abstract types (type=ATOMIC)
775      * we give the benefit of the doubt and return true.
776      */

777
778     public static boolean isOrdered(int type) {
779         switch (type) {
780             case ATOMIC:
781             case INTEGER:
782             case DOUBLE:
783             case FLOAT:
784             case DECIMAL:
785             case NUMBER:
786             case BOOLEAN:
787             case STRING:
788             case ANY_URI:
789             case DATE_TIME:
790             case DATE:
791             case TIME:
792             case DAY_TIME_DURATION:
793             case YEAR_MONTH_DURATION:
794                 return true;
795             default:
796                 return false;
797         }
798     }
799
800     /**
801      * Test whether the supplied type, which must be a primitive type, is one of
802      * the numeric primitive types
803      * @param t the type being tested
804      * @return true if the type is integer, double, float, decimal, or the abstract type "numeric"
805      */

806     public static boolean isNumericPrimitiveType(ItemType t) {
807         if (t instanceof AtomicType) {
808             int fp = ((AtomicType)t).getFingerprint();
809             return fp==INTEGER || fp==DOUBLE || fp==FLOAT || fp==DECIMAL || fp==NUMBER;
810         } else {
811             return false;
812         }
813     }
814 }
815
816 //
817
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
818
// you may not use this file except in compliance with the License. You may obtain a copy of the
819
// License at http://www.mozilla.org/MPL/
820
//
821
// Software distributed under the License is distributed on an "AS IS" basis,
822
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
823
// See the License for the specific language governing rights and limitations under the License.
824
//
825
// The Original Code is: all this file.
826
//
827
// The Initial Developer of the Original Code is Michael H. Kay
828
//
829
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
830
//
831
// Contributor(s): none.
832
//
833
Popular Tags