KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > pattern > ContentTypeTest


1 package net.sf.saxon.pattern;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.tinytree.TinyTree;
4 import net.sf.saxon.functions.Nilled;
5 import net.sf.saxon.om.NodeInfo;
6 import net.sf.saxon.om.NamePool;
7 import net.sf.saxon.style.StandardNames;
8 import net.sf.saxon.type.*;
9
10 /**
11  * NodeTest is an interface that enables a test of whether a node matches particular
12  * conditions. ContentTypeTest tests for an element or attribute node with a particular
13  * type annotation.
14   *
15   * @author Michael H. Kay
16   */

17
18 public class ContentTypeTest extends NodeTest {
19
20     private int kind; // element or attribute
21
private SchemaType schemaType;
22     private int requiredType;
23     private Configuration config;
24     private boolean nillable = false;
25     private boolean matchDTDTypes = false;
26
27     // TODO: need to consider "issue 309": what happens when the document contains
28
// a type annotation that wasn't known at stylesheet compile time? It might be
29
// a subtype of the required type.
30

31     /**
32      * Create a ContentTypeTest
33      * @param nodeKind the kind of nodes to be matched: always elements or attributes
34      * @param schemaType the required type annotation, as a simple or complex schema type
35      * @param config the Configuration, supplied because this KindTest needs access to schema information
36      */

37
38     public ContentTypeTest(int nodeKind, SchemaType schemaType, Configuration config) {
39         this.kind = nodeKind;
40         this.schemaType = schemaType;
41         this.requiredType = schemaType.getFingerprint();
42         if (requiredType == -1) {
43             requiredType = StandardNames.XDT_UNTYPED; // probably doesn't happen
44
}
45         this.config = config;
46     }
47
48     /**
49      * Indicate whether nilled elements should be matched (the default is false)
50      * @param nillable true if nilled elements should be matched
51      */

52     public void setNillable(boolean nillable) {
53         this.nillable = nillable;
54     }
55
56     /**
57      * The test is nillable if "?" was specified in the SequenceType syntax
58      * @return true if the test is nillable
59      */

60
61     public boolean isNillable() {
62         return nillable;
63     }
64
65     /**
66      * Indicate whether DTD-derived content types should be matched (the default is false)
67      * @param matched true if DTD-derived types should be matched. If false, DTD-derived types are treated
68      * as untypedAtomic
69      */

70
71     public void setMatchDTDTypes(boolean matched) {
72         this.matchDTDTypes = matched;
73     }
74
75     /**
76      * Test whether DTD-derived content types should be matched (the default is false)
77      * @return true if DTD-derived types should be matched. If false, DTD-derived types are treated
78      * as untypedAtomic
79      */

80
81     public boolean matchesDTDTypes() {
82         return matchDTDTypes;
83     }
84
85     public SchemaType getSchemaType() {
86         return schemaType;
87     }
88
89     public ItemType getSuperType() {
90         return NodeKindTest.makeNodeKindTest(kind);
91     }
92
93     /**
94     * Test whether this node test is satisfied by a given node
95     * @param nodeKind The type of node to be matched
96      * @param fingerprint identifies the expanded name of the node to be matched
97      * @param annotation The actual content type of the node
98      */

99
100     public boolean matches(int nodeKind, int fingerprint, int annotation) {
101         if (kind != nodeKind) {
102             return false;
103         }
104         return matchesAnnotation(annotation);
105     }
106
107     /**
108      * Test whether this node test is satisfied by a given node on a TinyTree. The node
109      * must be a document, element, text, comment, or processing instruction node.
110      * This method is provided
111      * so that when navigating a TinyTree a node can be rejected without
112      * actually instantiating a NodeInfo object.
113      *
114      * @param tree the TinyTree containing the node
115      * @param nodeNr the number of the node within the TinyTree
116      * @return true if the node matches the NodeTest, otherwise false
117      */

118
119     public boolean matches(TinyTree tree, int nodeNr) {
120         if (kind != tree.getNodeKind(nodeNr)) {
121             return false;
122         }
123         return matchesAnnotation(tree.getTypeAnnotation(nodeNr))
124             && (nillable || !tree.isNilled(nodeNr));
125     }
126
127     /**
128      * Test whether this node test is satisfied by a given node. This alternative
129      * method is used in the case of nodes where calculating the fingerprint is expensive,
130      * for example DOM or JDOM nodes.
131      * @param node the node to be matched
132      */

133
134     public boolean matches(NodeInfo node) {
135         return node.getNodeKind() == kind &&
136                 matchesAnnotation(node.getTypeAnnotation())
137                 && (nillable || !Nilled.isNilled(node));
138     }
139
140     private boolean matchesAnnotation(int annotation) {
141         if (requiredType == StandardNames.XS_ANY_TYPE) {
142             return true;
143         }
144
145         if (annotation == -1) {
146             annotation = (kind==Type.ATTRIBUTE ? StandardNames.XDT_UNTYPED_ATOMIC : StandardNames.XDT_UNTYPED);
147         }
148
149         if (matchDTDTypes) {
150             annotation = annotation & NamePool.FP_MASK;
151         } else if (((annotation & NodeInfo.IS_DTD_TYPE) != 0)) {
152             return (requiredType == StandardNames.XDT_UNTYPED_ATOMIC);
153         }
154
155         if (annotation == requiredType) {
156             return true;
157         }
158
159         // see if the type annotation is a subtype of the required type
160
try { // TODO: this is expensive. Do some caching
161
SchemaType type = config.getSchemaType(annotation & NamePool.FP_MASK).getBaseType();
162             while (type != null) {
163                 if (type.getFingerprint() == requiredType) {
164                     return true;
165                 }
166                 type = type.getBaseType();
167             }
168         } catch (UnresolvedReferenceException e) {
169             throw new IllegalStateException JavaDoc(e.getMessage());
170         }
171         return false;
172     }
173
174     /**
175     * Determine the default priority of this node test when used on its own as a Pattern
176     */

177
178     public final double getDefaultPriority() {
179         return 0;
180     }
181
182     /**
183     * Determine the types of nodes to which this pattern applies. Used for optimisation.
184     * @return the type of node matched by this pattern. e.g. Type.ELEMENT or Type.TEXT
185     */

186
187     public int getPrimitiveType() {
188         return kind;
189     }
190
191     /**
192      * Get a mask indicating which kinds of nodes this NodeTest can match. This is a combination
193      * of bits: 1<<Type.ELEMENT for element nodes, 1<<Type.TEXT for text nodes, and so on.
194      */

195
196     public int getNodeKindMask() {
197         return 1<<kind;
198     }
199
200     /**
201      * Get the content type allowed by this NodeTest (that is, the type annotation of the matched nodes).
202      * Return AnyType if there are no restrictions. The default implementation returns AnyType.
203      */

204
205     public SchemaType getContentType() {
206         return schemaType;
207     }
208
209     /**
210      * Get the item type of the atomic values that will be produced when an item
211      * of this type is atomized (assuming that atomization succeeds)
212      */

213
214     public AtomicType getAtomizedItemType() {
215         SchemaType type = config.getSchemaType(requiredType);
216         if (type instanceof AtomicType) {
217             return (AtomicType)type;
218         } else if (type instanceof ListType) {
219             SimpleType mem = ((ListType)type).getItemType();
220             if (mem instanceof AtomicType) {
221                 return (AtomicType)mem;
222             }
223         }
224         return Type.ANY_ATOMIC_TYPE;
225     }
226
227     public String JavaDoc toString() {
228         return (kind == Type.ELEMENT ? "element(*, " : "attribute(*, ") +
229                         schemaType.getDescription() + ')';
230     }
231
232     /**
233       * Returns a hash code value for the object.
234       */

235
236      public int hashCode() {
237          return kind<<20 ^ requiredType;
238      }
239
240 }
241
242 //
243
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
244
// you may not use this file except in compliance with the License. You may obtain a copy of the
245
// License at http://www.mozilla.org/MPL/
246
//
247
// Software distributed under the License is distributed on an "AS IS" basis,
248
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
249
// See the License for the specific language governing rights and limitations under the License.
250
//
251
// The Original Code is: all this file.
252
//
253
// The Initial Developer of the Original Code is Michael H. Kay.
254
//
255
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
256
//
257
// Contributor(s): none.
258
//
259
Popular Tags