1 package net.sf.saxon.expr; 2 import net.sf.saxon.om.Item; 3 import net.sf.saxon.om.NamePool; 4 import net.sf.saxon.om.SequenceIterator; 5 import net.sf.saxon.trans.StaticError; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.AnyItemType; 8 import net.sf.saxon.type.ItemType; 9 import net.sf.saxon.type.Type; 10 import net.sf.saxon.value.Value; 11 import net.sf.saxon.value.Cardinality; 12 import net.sf.saxon.event.SequenceReceiver; 13 import net.sf.saxon.event.TypeCheckingFilter; 14 import net.sf.saxon.pattern.DocumentNodeTest; 15 16 20 21 public final class ItemChecker extends UnaryExpression { 22 23 private ItemType requiredItemType; 24 private RoleLocator role; 25 26 29 30 public ItemChecker(Expression sequence, ItemType itemType, RoleLocator role) { 31 super(sequence); 32 this.requiredItemType = itemType; 33 this.role = role; 34 adoptChildExpression(sequence); 35 } 36 37 40 41 public ItemType getRequiredType() { 42 return requiredItemType; 43 } 44 45 48 49 public Expression simplify(StaticContext env) throws XPathException { 50 operand = operand.simplify(env); 51 if (requiredItemType instanceof AnyItemType) { 52 return operand; 53 } 54 return this; 55 } 56 57 60 61 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 62 operand = operand.typeCheck(env, contextItemType); 63 65 ItemType supplied = operand.getItemType(); 66 int relation = Type.relationship(requiredItemType, supplied); 67 if (relation == Type.SAME_TYPE || relation == Type.SUBSUMES) { 68 return operand; 69 } 70 if (relation == Type.DISJOINT) { 71 String message = role.composeErrorMessage(requiredItemType, operand.getItemType(), env.getNamePool()); 76 StaticError err = new StaticError(message); 77 err.setErrorCode(role.getErrorCode()); 78 err.setLocator(this); 79 err.setIsTypeError(true); 80 throw err; 81 } 82 return this; 83 } 84 85 90 91 public int getImplementationMethod() { 92 int m = ITERATE_METHOD | PROCESS_METHOD; 93 if (!Cardinality.allowsMany(getCardinality())) { 94 m |= EVALUATE_METHOD; 95 } 96 return m; 97 } 98 99 100 103 104 public SequenceIterator iterate(XPathContext context) throws XPathException { 105 SequenceIterator base = operand.iterate(context); 106 ItemCheckMappingFunction map = new ItemCheckMappingFunction(); 107 map.externalContext = context; 108 return new MappingIterator(base, map, null); 109 } 110 111 115 private class ItemCheckMappingFunction implements MappingFunction { 116 public XPathContext externalContext; 117 public Object map(Item item, XPathContext nullcontext) throws XPathException { 118 testConformance(item, externalContext); 119 return item; 120 } 121 } 122 123 126 127 public Item evaluateItem(XPathContext context) throws XPathException { 128 Item item = operand.evaluateItem(context); 129 if (item==null) return null; 130 testConformance(item, context); 131 return item; 132 } 133 134 140 141 public void process(XPathContext context) throws XPathException { 142 Expression next = operand; 143 int card = StaticProperty.ALLOWS_ZERO_OR_MORE; 144 if (next instanceof CardinalityChecker) { 145 card = ((CardinalityChecker)next).getRequiredCardinality(); 146 next = ((CardinalityChecker)next).getBaseExpression(); 147 } 148 if ((next.getImplementationMethod() & PROCESS_METHOD) != 0 && !(requiredItemType instanceof DocumentNodeTest)) { 149 SequenceReceiver out = context.getReceiver(); 150 TypeCheckingFilter filter = new TypeCheckingFilter(); 151 filter.setUnderlyingReceiver(out); 152 filter.setPipelineConfiguration(out.getPipelineConfiguration()); 153 filter.setRequiredType(requiredItemType, card, role); 154 context.setReceiver(filter); 155 next.process(context); 156 filter.close(); 157 context.setReceiver(filter); 158 } else { 159 super.process(context); 160 } 161 } 162 163 164 165 private void testConformance(Item item, XPathContext context) throws XPathException { 166 if (!requiredItemType.matchesItem(item)) { 167 String message; 168 if (context == null) { 169 message = "Supplied value of type " + Type.displayTypeName(item) + 171 " does not match the required type of " + role.getMessage(); 172 } else { 173 NamePool pool = context.getController().getNamePool(); 174 message = role.composeErrorMessage(requiredItemType, Value.asValue(item).getItemType(), pool); 175 } 179 String errorCode = role.getErrorCode(); 180 if ("XPDY0050".equals(errorCode)) { 181 dynamicError(message, errorCode, context); 183 } else { 184 typeError(message, errorCode, context); 185 } 186 } 187 } 188 189 192 193 public ItemType getItemType() { 194 return requiredItemType; 196 } 197 198 201 202 public boolean equals(Object other) { 203 return super.equals(other) && 204 requiredItemType == ((ItemChecker)other).requiredItemType; 205 } 206 207 211 212 protected String displayOperator(NamePool pool) { 213 return "treat as " + requiredItemType.toString(pool); 214 } 215 216 } 217 218 219 220 | Popular Tags |