1 package net.sf.saxon.expr; 2 import net.sf.saxon.Configuration; 3 import net.sf.saxon.om.*; 4 import net.sf.saxon.pattern.NodeTest; 5 import net.sf.saxon.pattern.NoNodeTest; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.*; 8 import net.sf.saxon.value.AtomicValue; 9 import net.sf.saxon.value.Cardinality; 10 import net.sf.saxon.value.Value; 11 12 16 17 public final class Atomizer extends UnaryExpression { 18 19 private boolean untyped; 21 27 28 public Atomizer(Expression sequence, Configuration config) { 29 super(sequence); 30 31 if (config == null) { 32 untyped = false; 33 } else { 34 untyped = config.areAllNodesUntyped(); 35 } 36 } 37 38 41 42 public Expression simplify(StaticContext env) throws XPathException { 43 if (!env.getConfiguration().isSchemaAware(Configuration.XML_SCHEMA)) { 44 untyped = true; 45 }; 46 operand = operand.simplify(env); 47 if (operand instanceof AtomicValue) { 48 return operand; 49 } else if (operand instanceof Value) { 50 SequenceIterator iter = operand.iterate(null); 51 while (true) { 52 Item i = iter.next(); 55 if (i == null) { 56 return operand; 57 } 58 if (i instanceof NodeInfo) { 59 return this; 60 } 61 } 62 } 63 return this; 64 } 65 66 69 70 public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException { 71 if (!env.getConfiguration().isSchemaAware(Configuration.XML_SCHEMA)) { 72 untyped = true; 73 }; 74 operand = operand.typeCheck(env, contextItemType); 75 resetStaticProperties(); 76 if (Type.isSubType(operand.getItemType(), Type.ANY_ATOMIC_TYPE)) { 77 return operand; 78 } 79 return this; 80 } 81 82 83 87 88 public int computeSpecialProperties() { 89 int p = super.computeSpecialProperties(); 90 return p | StaticProperty.NON_CREATIVE; 91 } 92 93 96 97 public SequenceIterator iterate(XPathContext context) throws XPathException { 98 SequenceIterator base = operand.iterate(context); 99 if (base instanceof AtomizableIterator) { 100 ((AtomizableIterator)base).setIsAtomizing(true); 101 } 102 return AtomizingFunction.getAtomizingIterator(base); 103 } 104 105 109 110 public Item evaluateItem(XPathContext context) throws XPathException { 111 Item i = operand.evaluateItem(context); 112 if (i==null) { 113 return null; 114 } 115 if (i instanceof NodeInfo) { 116 SequenceIterator it = i.getTypedValue(); 117 return it.next(); 118 } else { 119 return i; 120 } 121 } 122 123 126 127 public static class AtomizingFunction implements MappingFunction { 128 129 132 133 private AtomizingFunction(){}; 134 135 private static final AtomizingFunction theInstance = new AtomizingFunction(); 136 137 141 142 public static AtomizingFunction getInstance() { 143 return theInstance; 144 } 145 146 public static SequenceIterator getAtomizingIterator(SequenceIterator base) { 147 return new MappingIterator(base, theInstance, null); 148 } 149 150 public Object map(Item item, XPathContext context) throws XPathException { 151 if (item instanceof NodeInfo) { 152 return item.getTypedValue(); 153 } else { 154 return item; 155 } 156 } 157 } 158 159 164 165 public ItemType getItemType() { 166 return getAtomizedItemType(operand, untyped); 167 } 168 169 175 176 public static final ItemType getAtomizedItemType(Expression operand, boolean alwaysUntyped) { 177 ItemType in = operand.getItemType(); 178 if (in instanceof AtomicType) { 179 return in; 180 } 181 if (in instanceof NodeTest) { 182 183 if (in instanceof NoNodeTest) { 184 return in; 185 } 186 int kinds = ((NodeTest)in).getNodeKindMask(); 187 if (alwaysUntyped) { 188 190 if ((kinds | STRING_KINDS) == STRING_KINDS) { 191 return Type.STRING_TYPE; 192 } 193 196 if ((kinds | UNTYPED_IF_UNTYPED_KINDS) == UNTYPED_IF_UNTYPED_KINDS) { 197 return Type.UNTYPED_ATOMIC_TYPE; 198 } 199 } else { 200 if ((kinds | UNTYPED_KINDS) == UNTYPED_KINDS) { 201 return Type.UNTYPED_ATOMIC_TYPE; 202 } 203 } 204 205 SchemaType schemaType = ((NodeTest)in).getContentType(); 206 if (schemaType instanceof SimpleType) { 207 return ((SimpleType)schemaType).getCommonAtomicType(); 208 } else if (((ComplexType)schemaType).isSimpleContent()) { 209 return ((ComplexType)schemaType).getSimpleContentType().getCommonAtomicType(); 210 } else if (schemaType instanceof AnyType) { 211 return Type.ANY_ATOMIC_TYPE; 214 } else { 215 return Type.UNTYPED_ATOMIC_TYPE; 218 } 219 } 220 return Type.ANY_ATOMIC_TYPE; 221 } 222 223 226 private static final int STRING_KINDS = 227 (1<<Type.NAMESPACE) | (1<<Type.COMMENT) | (1<<Type.PROCESSING_INSTRUCTION); 228 229 232 233 private static final int UNTYPED_KINDS = 234 (1<<Type.TEXT) | (1<<Type.DOCUMENT); 235 236 239 240 private static final int UNTYPED_IF_UNTYPED_KINDS = 241 (1<<Type.TEXT) | (1<<Type.ELEMENT) | (1<<Type.DOCUMENT) | (1<<Type.ATTRIBUTE); 242 243 246 247 public int computeCardinality() { 248 if (untyped) { 249 return operand.getCardinality(); 250 } else { 251 if (Cardinality.allowsMany(operand.getCardinality())) { 252 return StaticProperty.ALLOWS_ZERO_OR_MORE; 253 } 254 ItemType in = operand.getItemType(); 255 if (in instanceof AtomicType) { 256 return operand.getCardinality(); 257 } 258 if (in instanceof NodeTest) { 259 SchemaType schemaType = ((NodeTest)in).getContentType(); 260 if (schemaType instanceof AtomicType) { 261 return operand.getCardinality(); 263 } 264 } 265 return StaticProperty.ALLOWS_ZERO_OR_MORE; 266 } 267 } 268 269 273 274 protected String displayOperator(NamePool pool) { 275 return "atomize"; 276 } 277 278 } 279 280 281 282 | Popular Tags |