1 package net.sf.saxon.event; 2 3 import net.sf.saxon.expr.Token; 4 import net.sf.saxon.expr.RoleLocator; 5 import net.sf.saxon.expr.ExpressionLocation; 6 import net.sf.saxon.om.Item; 7 import net.sf.saxon.om.NamePool; 8 import net.sf.saxon.pattern.CombinedNodeTest; 9 import net.sf.saxon.pattern.ContentTypeTest; 10 import net.sf.saxon.pattern.NameTest; 11 import net.sf.saxon.pattern.NodeKindTest; 12 import net.sf.saxon.trans.XPathException; 13 import net.sf.saxon.trans.DynamicError; 14 import net.sf.saxon.type.ItemType; 15 import net.sf.saxon.type.Type; 16 import net.sf.saxon.value.Value; 17 import net.sf.saxon.value.Cardinality; 18 19 import java.util.HashSet ; 20 21 29 30 public class TypeCheckingFilter extends ProxyReceiver { 31 32 private ItemType itemType; 33 private int cardinality; 34 private RoleLocator role; 35 private int count = 0; 36 private int level = 0; 37 private HashSet checkedElements = new HashSet (10); 38 40 public void setRequiredType(ItemType type, int cardinality, RoleLocator role) { 41 this.itemType = type; 42 this.cardinality = cardinality; 43 this.role = role; 44 } 45 46 58 59 public void attribute(int nameCode, int typeCode, CharSequence value, int locationId, int properties) throws XPathException { 60 if (level == 0) { 61 if (++count == 2) { 62 checkAllowsMany(locationId); 63 } 64 ItemType type = new CombinedNodeTest( 65 new NameTest(Type.ATTRIBUTE, nameCode, getNamePool()), 66 Token.INTERSECT, 67 new ContentTypeTest(Type.ATTRIBUTE, getConfiguration().getSchemaType(typeCode), getConfiguration())); 68 checkItemType(type, locationId); 69 } 70 super.attribute(nameCode, typeCode, value, locationId, properties); 71 } 72 73 76 77 public void characters(CharSequence chars, int locationId, int properties) throws XPathException { 78 if (level == 0) { 79 if (++count == 2) { 80 checkAllowsMany(locationId); 81 } 82 ItemType type = NodeKindTest.TEXT; 83 checkItemType(type, locationId); 84 } 85 super.characters(chars, locationId, properties); 86 } 87 88 91 92 public void comment(CharSequence chars, int locationId, int properties) throws XPathException { 93 if (level == 0) { 94 if (++count == 2) { 95 checkAllowsMany(locationId); 96 } 97 ItemType type = NodeKindTest.COMMENT; 98 checkItemType(type, locationId); 99 } 100 super.comment(chars, locationId, properties); } 102 103 116 117 public void namespace(int namespaceCode, int properties) throws XPathException { 118 if (level == 0) { 119 if (++count == 2) { 120 checkAllowsMany(0); 121 } 122 ItemType type = NodeKindTest.NAMESPACE; 123 checkItemType(type, 0); 124 } 125 super.namespace(namespaceCode, properties); } 127 128 131 132 public void processingInstruction(String target, CharSequence data, int locationId, int properties) throws XPathException { 133 if (level == 0) { 134 if (++count == 2) { 135 checkAllowsMany(locationId); 136 } 137 ItemType type = NodeKindTest.PROCESSING_INSTRUCTION; 138 checkItemType(type, locationId); 139 } 140 super.processingInstruction(target, data, locationId, properties); 141 } 142 143 146 147 public void startDocument(int properties) throws XPathException { 148 if (level == 0) { 149 if (++count == 2) { 150 checkAllowsMany(0); 151 } 152 ItemType type = NodeKindTest.DOCUMENT; 153 checkItemType(type, 0); 154 } 155 level++; 156 super.startDocument(properties); 157 } 158 159 166 167 public void startElement(int nameCode, int typeCode, int locationId, int properties) throws XPathException { 168 if (level == 0) { 169 if (++count == 1) { 170 ItemType type = new CombinedNodeTest( 172 new NameTest(Type.ELEMENT, nameCode, getNamePool()), 173 Token.INTERSECT, 174 new ContentTypeTest(Type.ELEMENT, getConfiguration().getSchemaType(typeCode), getConfiguration())); 175 checkItemType(type, locationId); 176 } else { 177 if (count == 2) { 178 checkAllowsMany(locationId); 179 } 180 Long key = new Long (((long)(nameCode&NamePool.FP_MASK))<<32 | (long)(typeCode&NamePool.FP_MASK)); 181 if (!checkedElements.contains(key)) { 182 ItemType type = new CombinedNodeTest( 183 new NameTest(Type.ELEMENT, nameCode, getNamePool()), 184 Token.INTERSECT, 185 new ContentTypeTest(Type.ELEMENT, getConfiguration().getSchemaType(typeCode), getConfiguration())); 186 checkItemType(type, locationId); 187 checkedElements.add(key); 188 } 189 } 190 } 191 level++; 192 super.startElement(nameCode, typeCode, locationId, properties); 193 } 194 195 198 199 public void endDocument() throws XPathException { 200 level--; 201 super.endDocument(); 202 } 203 204 207 208 public void endElement() throws XPathException { 209 level--; 210 super.endElement(); 211 } 212 213 216 217 public void close() throws XPathException { 218 if (count == 0 && !Cardinality.allowsZero(cardinality)) { 219 DynamicError err = new DynamicError( 220 "An empty sequence is not allowed as the " + 221 role.getMessage()); 222 String errorCode = role.getErrorCode(); 223 err.setErrorCode(errorCode); 224 if (!"XPDY0050".equals(errorCode)) { 225 err.setIsTypeError(true); 226 } 227 throw err; 228 } 229 } 231 232 235 236 public void append(Item item, int locationId, int copyNamespaces) throws XPathException { 237 if (level == 0) { 238 if (++count == 2) { 239 checkAllowsMany(locationId); 240 } 241 checkItemType(Value.asValue(item).getItemType(), locationId); 242 } 243 if (nextReceiver instanceof SequenceReceiver) { 244 ((SequenceReceiver)nextReceiver).append(item, locationId, copyNamespaces); 245 } else { 246 super.append(item, locationId, copyNamespaces); 247 } 248 } 249 250 private void checkItemType(ItemType type, int locationId) throws DynamicError { 251 if (!Type.isSubType(type, itemType)) { 252 String message = role.composeErrorMessage(itemType, type, getNamePool()); 253 String errorCode = role.getErrorCode(); 254 DynamicError err = new DynamicError(message); 255 err.setErrorCode(errorCode); 256 if (!"XPDY0050".equals(errorCode)) { 257 err.setIsTypeError(true); 258 } 259 err.setLocator(ExpressionLocation.getSourceLocator(locationId, 260 getPipelineConfiguration().getLocationProvider())); 261 throw err; 262 } 263 } 264 265 private void checkAllowsMany(int locationId) throws XPathException { 266 if (!Cardinality.allowsMany(cardinality)) { 267 DynamicError err = new DynamicError( 268 "A sequence of more than one item is not allowed as the " + 269 role.getMessage()); 270 String errorCode = role.getErrorCode(); 271 err.setErrorCode(errorCode); 272 if (!"XPDY0050".equals(errorCode)) { 273 err.setIsTypeError(true); 274 } 275 err.setLocator(ExpressionLocation.getSourceLocator(locationId, 276 getPipelineConfiguration().getLocationProvider())); 277 throw err; 278 } 279 } 280 281 282 283 } 284 285 | Popular Tags |