| 1 4 package gnu.xquery.util; 5 import gnu.mapping.*; 6 import gnu.xml.*; 7 import gnu.kawa.xml.*; 8 import gnu.lists.*; 9 import java.util.Stack ; 10 import java.net.*; 11 import gnu.text.URI_utils; 12 import gnu.expr.PrimProcedure; 13 import gnu.bytecode.ClassType; 14 import gnu.xquery.lang.XQuery; 15 16 public class NodeUtils 17 { 18 public static String name (Object node) 19 { 20 if (node == Values.empty || node == null) 21 return ""; 22 Object name = NodeName.nodeName(node); 23 if (name == null || name == Values.empty) 24 return ""; 25 return name.toString(); 26 } 27 28 public static String localName (Object node) 29 { 30 if (node == Values.empty || node == null) 31 return ""; 32 if (! (node instanceof KNode)) 33 throw new WrongType("local-name", 1, node, "node()?"); 34 Object name = NodeName.nodeName(node); 35 if (name == null || name == Values.empty) 36 return ""; 37 return ((Symbol) name).getName(); 38 } 39 40 public static Object namespaceURI (Object node) 41 { 42 if (node == Values.empty || node == null) 43 return ""; 44 if (! (node instanceof KNode)) 45 throw new WrongType("namespace-uri", 1, node, "node()?"); 46 Object name = NodeName.nodeName(node); 47 if (name == null || name == Values.empty) 48 return ""; 49 return QNameUtils.namespaceURIFromQName(name); 50 } 51 52 public static void prefixesFromNodetype (XName name, Consumer out) 53 { 54 NamespaceBinding bindings = ((XName) name).getNamespaceNodes(); 55 for (NamespaceBinding ns = bindings; 56 ns != null; 57 ns = ns.getNext()) 58 { 59 String prefix = ns.getPrefix(); 60 for (NamespaceBinding ns2 = bindings; ; ns2 = ns2.getNext()) 63 { 64 if (ns2 == ns) 65 { 66 out.writeObject(prefix == null ? "" : prefix); 67 break; 68 } 69 if (ns2.getPrefix() == prefix) 70 { 71 break; 73 } 74 } 75 } 76 } 77 78 public static void inScopePrefixes$X (Object node, CallContext ctx) 79 { 80 { 82 KElement element = (KElement) node; 83 Object type = element.sequence.getNextTypeObject(element.ipos); 84 if (type instanceof XName) 85 prefixesFromNodetype((XName) type, ctx.consumer); 86 else 87 ctx.consumer.writeObject("xml"); 88 } 89 } 90 91 public static void data$X (Object arg, CallContext ctx) 92 { 93 Consumer out = ctx.consumer; 94 if (arg instanceof Values) 95 { 96 Values vals = (Values) arg; 97 int ipos = vals.startPos(); 98 while ((ipos = vals.nextPos(ipos)) != 0) 99 out.writeObject(KNode.atomicValue(vals.getPosPrevious(ipos))); 100 } 101 else 102 out.writeObject(KNode.atomicValue(arg)); 103 } 104 105 106 public static Object root (Object arg) 107 { 108 if (arg == null || arg == Values.empty) 109 return arg; 110 if (! (arg instanceof KNode)) 111 throw new WrongType("root", 1, arg, "node()?"); 112 KNode node = (KNode) arg; 113 return Nodes.root((NodeTree) node.sequence, node.getPos()); 114 } 115 116 public static String getLang (KNode node) 117 { 118 NodeTree seq = (NodeTree) node.sequence; 119 int attr = seq.ancestorAttribute(node.ipos, 120 gnu.xml.NamespaceBinding.XML_NAMESPACE, 121 "lang"); 122 if (attr == 0) 123 return null; 124 else 125 return KNode.getNodeValue(seq, attr); 126 } 127 128 public static boolean lang (Object testlang, Object node) 129 { 130 String teststr; 131 if (testlang == null || testlang == Values.empty) 132 teststr = ""; 133 else 134 teststr = TextUtils.stringValue(testlang); 135 String lang = getLang((KNode) node); 136 if (lang == null) 137 return false; 138 int langlen = lang.length(); 139 int testlen = teststr.length(); 140 if (langlen > testlen && lang.charAt(testlen) == '-') 141 lang = lang.substring(0, testlen); 142 return lang.equalsIgnoreCase(teststr); 143 } 144 145 public static Object documentUri (Object arg) 146 { 147 if (arg == null || arg == Values.empty) 148 return arg; 149 if (! (arg instanceof KNode)) 150 throw new WrongType("xs:document-uri", 1, arg, "node()?"); 151 KNode node = (KNode) arg; 152 Object uri = ((NodeTree) node.sequence).documentUriOfPos(node.ipos); 153 return uri == null ? Values.empty : uri; 154 } 155 156 public static Object nilled (Object arg) 157 { 158 if (arg == null || arg == Values.empty) 159 return arg; 160 if (! (arg instanceof KNode)) 161 throw new WrongType("nilled", 1, arg, "node()?"); 162 if (! (arg instanceof KElement)) 163 return Values.empty; 164 return Boolean.FALSE; 165 } 166 167 public static Object baseUri (Object arg) 168 { 169 if (arg == null || arg == Values.empty) 170 return arg; 171 if (! (arg instanceof KNode)) 172 throw new WrongType("base-uri", 1, arg, "node()?"); 173 Object uri = ((KNode) arg).baseURI(); 174 return uri == null ? Values.empty : uri; 175 } 176 177 178 180 185 static Object getIDs (Object arg, Object collector) 186 { 187 if (arg instanceof KNode) 188 arg = KNode.atomicValue(arg); 189 if (arg instanceof Values) 190 { 191 Object [] ar = ((Values) arg).getValues(); 192 for (int i = ar.length; --i >= 0; ) 193 collector = getIDs(ar[i], collector); 194 } 195 else 196 { 197 String str = StringUtils.coerceToString(arg, "fn:id", 1, ""); 198 int len = str.length(); 199 int i = 0; 200 while (i < len) 201 { 202 char ch = str.charAt(i++); 203 if (Character.isWhitespace(ch)) 204 continue; 205 int start = XName.isNameStart(ch) ? i - 1 : len; 206 while (i < len) 207 { 208 ch = str.charAt(i); 209 if (Character.isWhitespace(ch)) 210 break; 211 i++; 212 if (start < len && ! XName.isNamePart(ch)) 213 start = len; 214 } 215 if (start < len) 216 { 217 String ref = str.substring(start, i); 218 if (collector == null) 219 collector = ref; 220 else 221 { 222 Stack st; 223 if (collector instanceof Stack ) 224 st = (Stack ) collector; 225 else 226 { 227 st = new Stack (); 228 st.push(collector); 229 collector = st; 230 } 231 st.push(ref); 232 } 233 } 234 i++; 235 } 236 } 237 return collector; 238 } 239 240 public static void id$X (Object arg1, Object arg2, CallContext ctx) 241 { 242 KNode node = (KNode) arg2; 243 NodeTree ntree = (NodeTree) node.sequence; 244 KDocument root 245 = (KDocument) Nodes.root(ntree, node.ipos); 246 Consumer out = ctx.consumer; 247 Object idrefs = getIDs(arg1, null); 248 if (idrefs == null) 249 return; 250 ntree.makeIDtableIfNeeded(); 251 if (out instanceof PositionConsumer 252 && (idrefs instanceof String || out instanceof SortedNodes)) 253 idScan(idrefs, ntree, (PositionConsumer) out); 254 else if (idrefs instanceof String ) 255 { 256 int pos = ntree.lookupID((String ) idrefs); 257 if (pos != -1) 258 out.writeObject(KNode.make(ntree, pos)); 259 } 260 else 261 { 262 SortedNodes nodes = new SortedNodes(); 263 idScan(idrefs, ntree, nodes); 264 Values.writeValues(nodes, out); 265 } 266 } 267 268 private static void idScan (Object ids, NodeTree seq, PositionConsumer out) 269 { 270 if (ids instanceof String ) 271 { 272 int pos = seq.lookupID((String ) ids); 273 if (pos != -1) 274 out.writePosition(seq, pos); 275 } 276 else if (ids instanceof Stack ) 277 { 278 Stack st = (Stack ) ids; 279 int n = st.size(); 280 for (int i = 0; i < n; i++) 281 idScan(st.elementAt(i), seq, out); 282 } 283 } 284 285 public static Object idref (Object arg1, Object arg2) 286 { 287 KNode node = (KNode) arg2; 288 KDocument root 289 = (KDocument) Nodes.root((NodeTree) node.sequence, node.getPos()); 290 return Values.empty; 291 } 292 293 294 static String collectionNamespace = "http://gnu.org/kawa/cached-collections"; 295 296 297 public static void setSavedCollection (Object uri, Object value, 298 Environment env) 299 { 300 if (uri == null) 301 uri = "#default"; 302 Symbol sym = Symbol.make(collectionNamespace, uri.toString()); 303 env.put(sym, null, value); 304 } 305 306 307 public static void setSavedCollection (Object uri, Object value) 308 { 309 setSavedCollection(uri, value, Environment.getCurrent()); 310 } 311 312 315 public static Object getSavedCollection (Object uri, Environment env) 316 { 317 if (uri == null) 318 uri = "#default"; 319 Symbol sym = Symbol.make(collectionNamespace, uri.toString()); 320 Object coll = env.get(sym, null, null); 321 if (coll == null) 322 throw new RuntimeException ("collection '"+uri+"' not found"); 323 return coll; 324 } 325 326 329 public static Object getSavedCollection (Object uri) 330 { 331 return getSavedCollection(uri, Environment.getCurrent()); 332 } 333 334 335 public static final Symbol collectionResolverSymbol = 336 Symbol.make(XQuery.LOCAL_NAMESPACE, "collection-resolver", "qexo"); 337 338 public static Object collection (Object uri, Object base) 339 throws Throwable  340 { 341 uri = resolve(uri, base, "collection"); 342 Environment env = Environment.getCurrent(); 343 Symbol rsym = NodeUtils.collectionResolverSymbol; 344 Object rvalue = env.get(rsym, null, null); 345 if (rvalue == null) 346 { 347 rvalue = env.get(Symbol.makeWithUnknownNamespace(rsym.getLocalName(), 348 rsym.getPrefix()), 349 null, null); 350 } 351 String str; 352 int colon; 353 if (rvalue == null) 354 { 355 return getSavedCollection(uri); 356 } 357 else if ((rvalue instanceof String || rvalue instanceof UntypedAtomic) 358 && (colon = (str = rvalue.toString()).indexOf(':')) > 0) 359 { 360 String cname = str.substring(0, colon); 361 String mname = str.substring(colon+1); 362 Class rclass; 363 try 364 { 365 rclass = Class.forName(cname); 366 } 367 catch (ClassNotFoundException ex) 368 { 369 throw new RuntimeException ("invalid collection-resolver: class "+cname+" not found"); 370 } 371 catch (Throwable ex) 372 { 373 throw new RuntimeException ("invalid collection-resolver: "+ex); 374 } 375 ClassType rclassType = ClassType.make(cname); 376 rvalue = gnu.kawa.reflect.ClassMethods.apply(rclassType, mname, '\0', XQuery.instance); 377 if (rvalue == null) 378 throw new RuntimeException ("invalid collection-resolver: no method "+mname+" in "+cname); 379 } 380 if (! (rvalue instanceof Procedure)) 381 throw new RuntimeException ("invalid collection-resolver: "+rvalue); 382 return ((Procedure) rvalue).apply1(uri); 383 } 384 385 static Object resolve (Object uri, Object base, String fname) 386 throws Throwable  387 { 388 if (! (uri instanceof URL)) 389 { 390 if (! (uri instanceof java.io.File ) 391 392 && ! (uri instanceof URI) 393 394 ) 395 uri = StringUtils.coerceToString(uri, fname, 1, null); 396 if (uri == Values.empty || uri == null) 397 return null; 398 if (! URI_utils.isAbsolute(uri)) 399 { 400 if (base == null) 401 base = CallContext.getInstance().getBaseUri(); 402 uri = URI_utils.resolve(uri, base); 403 } 404 } 405 return uri; 406 } 407 408 412 public static Object docCached (Object uri, Object base) 413 throws Throwable  414 { 415 uri = resolve(uri, base, "doc"); 416 if (uri == null) 417 return Values.empty; 418 return Document.parseCached(uri); 419 } 420 421 426 public static boolean availableCached (Object uri, Object base) 427 throws Throwable  428 { 429 uri = resolve(uri, base, "doc-available"); 430 if (uri == null) 431 return false; 432 try 433 { 434 Document.parseCached(uri); 435 return true; 436 } 437 catch (Throwable ex) 438 { 439 return false; 440 } 441 } 442 } 443 | Popular Tags |