KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > xquery > lang > XQResolveNames


1 // Copyright (c) 2003, 2004, 2006 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.xquery.lang;
5 import gnu.expr.*;
6 import gnu.kawa.xml.*;
7 import gnu.xml.*;
8 import gnu.mapping.*;
9 import gnu.bytecode.*;
10 import gnu.kawa.reflect.StaticFieldLocation;
11 import gnu.kawa.functions.GetNamedPart;
12 import gnu.xquery.util.NamedCollator;
13 import gnu.xquery.util.QNameUtils;
14 import java.util.Vector JavaDoc;
15 import gnu.math.DateTime;
16 import gnu.math.IntNum;
17
18 public class XQResolveNames extends ResolveNames
19 {
20   XQParser parser;
21
22   /** Code number for the special <code>last</code> function. */
23   public static final int LAST_BUILTIN = -1;
24
25   /** Code number for the special <code>position</code> function. */
26   public static final int POSITION_BUILTIN = -2;
27
28   /** Value of {@code xs:QName()} constructor. */
29   public static final int XS_QNAME_BUILTIN = -3;
30
31   /** Code number for the special <code>compare</code> function. */
32   public static final int COMPARE_BUILTIN = -4;
33
34   /** Code number for the special <code>distinct-values</code> function. */
35   public static final int DISTINCT_VALUES_BUILTIN = -5;
36
37   /** Code number for the special <code>local-name</code> function. */
38   public static final int LOCAL_NAME_BUILTIN = -6;
39
40   /** Code number for the special <code>namespace-uri</code> function. */
41   public static final int NAMESPACE_URI_BUILTIN = -7;
42
43   /** Code number for the special <code>collection</code> function. */
44   public static final int COLLECTION_BUILTIN = -8;
45
46   /** Code number for the special <code>doc</code> function. */
47   public static final int DOC_BUILTIN = -9;
48
49   /** Code number for the special <code>doc-available</code> function. */
50   public static final int DOC_AVAILABLE_BUILTIN = -10;
51
52   /** Code number for the special <code>doc-available</code> function. */
53   public static final int BASE_URI_BUILTIN = -11;
54
55   /** Code number for the special <code>ressolve-uri</code> function. */
56   public static final int RESOLVE_URI_BUILTIN = -12;
57
58   /** Code number for internal function that maps prefix to uri. */
59   public static final int RESOLVE_PREFIX_BUILTIN = -13;
60
61   /** Code number for the special <code>static-base-uri</code> function. */
62   public static final int STATIC_BASE_URI_BUILTIN = -14;
63
64   /** Code number for the special <code>index-of</code> function. */
65   public static final int INDEX_OF_BUILTIN = -15;
66
67   /** Code number for the special <code>string</code> function. */
68   public static final int STRING_BUILTIN = -16;
69
70   /** Code number for the special <code>normalize-space</code> function. */
71   public static final int NORMALIZE_SPACE_BUILTIN = -17;
72
73   /** Code number for the special <code>unordered</code> function. */
74   public static final int UNORDERED_BUILTIN = -18;
75
76   /** Code number for the special <code>current-dateTime</code> function. */
77   public static final int CURRENT_DATETIME_BUILTIN = -19;
78
79   /** Code number for the special <code>current-date</code> function. */
80   public static final int CURRENT_DATE_BUILTIN = -20;
81
82   /** Code number for the special <code>current-time</code> function. */
83   public static final int CURRENT_TIME_BUILTIN = -21;
84
85   /** Code number for the special <code>implicit-timezone</code> function. */
86   public static final int IMPLICIT_TIMEZONE_BUILTIN = -22;
87
88   /** Code number for the special <code>lang</code> function. */
89   public static final int LANG_BUILTIN = -23;
90
91   /** Code number for the special <code>name</code> function. */
92   public static final int NAME_BUILTIN = -24;
93
94   /** Code number for the special <code>deep-equal</code> function. */
95   public static final int DEEP_EQUAL_BUILTIN = -25;
96
97   /** Code number for the special <code>min</code> function. */
98   public static final int MIN_BUILTIN = -26;
99
100   /** Code number for the special <code>max</code> function. */
101   public static final int MAX_BUILTIN = -27;
102
103   /** Code number for the special <code>number</code> function. */
104   public static final int NUMBER_BUILTIN = -28;
105
106   /** Code number for the special <code>default-collation</code> function. */
107   public static final int DEFAULT_COLLATION_BUILTIN = -29;
108
109   /** Code number for the special <code>id</code> function. */
110   public static final int ID_BUILTIN = -30;
111
112   /** Code number for the special <code>idref</code> function. */
113   public static final int IDREF_BUILTIN = -31;
114
115   /** Code number for the special <code>root</code> function. */
116   public static final int ROOT_BUILTIN = -32;
117
118   public static final int CAST_AS_BUILTIN = -33;
119   public static final int CASTABLE_AS_BUILTIN = -34;
120
121   /** Code number for internal function to handle extensions. */
122   public static final int HANDLE_EXTENSION_BUILTIN = -35;
123
124   public static final Declaration handleExtensionDecl
125     = makeBuiltin("(extension)", HANDLE_EXTENSION_BUILTIN);
126
127   public static final Declaration castAsDecl
128     = makeBuiltin("(cast as)", CAST_AS_BUILTIN);
129
130   public static final Declaration castableAsDecl
131     = makeBuiltin("(castable as)", CASTABLE_AS_BUILTIN);
132
133   /** Declaration for the <code>fn:last()</code> function. */
134   public static final Declaration lastDecl
135     = makeBuiltin("last", LAST_BUILTIN);
136
137   public Declaration currentDateTimeDecl;
138   public Declaration currentDateDecl;
139   public Declaration currentTimeDecl;
140   public Declaration currentTimezoneDecl;
141
142   public static final Declaration xsQNameDecl
143     = makeBuiltin(Symbol.make(XQuery.SCHEMA_NAMESPACE, "QName"), XS_QNAME_BUILTIN);
144
145   public static final Declaration staticBaseUriDecl
146     = makeBuiltin("static-base-uri", STATIC_BASE_URI_BUILTIN);
147
148   public static final Declaration resolvePrefixDecl
149     = makeBuiltin(Symbol.make(XQuery.SCHEMA_NAMESPACE, "(resolve-prefix)"),
150                   RESOLVE_PREFIX_BUILTIN);
151
152   /** Create a <code>Declaration</code> for a builtin function. */
153   public static Declaration makeBuiltin (String JavaDoc name, int code)
154   {
155     return makeBuiltin (Symbol.make(XQuery.XQUERY_FUNCTION_NAMESPACE, name, "fn"),
156             code);
157   }
158
159   /** Create a <code>Declaration</code> for a builtin function. */
160   public static Declaration makeBuiltin (Symbol name, int code)
161   {
162     Declaration decl = new Declaration(name);
163     decl.setProcedureDecl(true);
164     decl.setCode(code);
165     return decl;
166   }
167
168   public XQResolveNames ()
169   {
170     this(null);
171   }
172
173   void pushBuiltin (String JavaDoc name, int code)
174   {
175     lookup.push(makeBuiltin(name, code));
176   }
177
178   public XQResolveNames (Compilation comp)
179   {
180     super(comp);
181     lookup.push(lastDecl);
182     lookup.push(xsQNameDecl);
183     lookup.push(staticBaseUriDecl);
184     pushBuiltin("position", POSITION_BUILTIN);
185     pushBuiltin("compare", COMPARE_BUILTIN);
186     pushBuiltin("distinct-values", DISTINCT_VALUES_BUILTIN);
187     pushBuiltin("local-name", LOCAL_NAME_BUILTIN);
188     pushBuiltin("name", NAME_BUILTIN);
189     pushBuiltin("namespace-uri", NAMESPACE_URI_BUILTIN);
190     pushBuiltin("root", ROOT_BUILTIN);
191     pushBuiltin("base-uri", BASE_URI_BUILTIN);
192     pushBuiltin("lang", LANG_BUILTIN);
193     pushBuiltin("resolve-uri", RESOLVE_URI_BUILTIN);
194     pushBuiltin("collection", COLLECTION_BUILTIN);
195     pushBuiltin("doc", DOC_BUILTIN);
196     pushBuiltin("document", DOC_BUILTIN); // Obsolete
197
pushBuiltin("doc-available", DOC_AVAILABLE_BUILTIN);
198     pushBuiltin("index-of", INDEX_OF_BUILTIN);
199     pushBuiltin("string", STRING_BUILTIN);
200     pushBuiltin("normalize-space", NORMALIZE_SPACE_BUILTIN);
201     pushBuiltin("unordered", UNORDERED_BUILTIN);
202     pushBuiltin("current-dateTime", CURRENT_DATETIME_BUILTIN);
203     pushBuiltin("current-date", CURRENT_DATE_BUILTIN);
204     pushBuiltin("current-time", CURRENT_TIME_BUILTIN);
205     pushBuiltin("implicit-timezone", IMPLICIT_TIMEZONE_BUILTIN);
206     pushBuiltin("deep-equal", DEEP_EQUAL_BUILTIN);
207     pushBuiltin("min", MIN_BUILTIN);
208     pushBuiltin("max", MAX_BUILTIN);
209     pushBuiltin("number", NUMBER_BUILTIN);
210     pushBuiltin("default-collation", DEFAULT_COLLATION_BUILTIN);
211     pushBuiltin("id", ID_BUILTIN);
212     pushBuiltin("idref", IDREF_BUILTIN);
213   }
214
215   public Namespace[] functionNamespacePath
216     = XQuery.defaultFunctionNamespacePath;
217
218   protected void push (ScopeExp exp)
219   {
220     for (Declaration decl = exp.firstDecl();
221          decl != null; decl = decl.nextDecl())
222       {
223         push(decl);
224       }
225   }
226
227   void push (Declaration decl)
228   {
229     Compilation comp = getCompilation();
230     Object JavaDoc name = decl.getSymbol();
231     boolean function = decl.isProcedureDecl();
232     if (name instanceof String JavaDoc)
233       {
234         int line = decl.getLineNumber();
235         if (line > 0 && comp != null)
236           {
237             String JavaDoc saveFilename = comp.getFileName();
238             int saveLine = comp.getLineNumber();
239             int saveColumn = comp.getColumnNumber();
240             comp.setLocation(decl);
241             name = parser.namespaceResolve((String JavaDoc) name, function);
242             comp.setLine(saveFilename, saveLine, saveColumn);
243           }
244         else
245           name = parser.namespaceResolve((String JavaDoc) name, function);
246         if (name == null)
247           return;
248         decl.setName(name);
249       }
250
251     Declaration old = lookup.lookup(name, XQuery.instance.getNamespaceOf(decl));
252     if (old != null)
253       {
254         if (decl.context == old.context)
255           ScopeExp.duplicateDeclarationError(old, decl, comp);
256         else if (XQParser.warnHidePreviousDeclaration
257                  && (! (name instanceof Symbol)
258                      || ((Symbol) name).getNamespace() != null))
259           comp.error('w', decl, "declaration ",
260                      " hides previous declaration");
261       }
262     lookup.push(decl);
263   }
264
265   Declaration flookup (Symbol sym)
266   {
267     Environment env = XQuery.xqEnvironment;
268     gnu.mapping.Location loc = env.lookup(sym, EnvironmentKey.FUNCTION);
269     if (loc == null)
270       return null;
271     loc = loc.getBase();
272     if (loc instanceof StaticFieldLocation)
273       {
274     Declaration decl = ((StaticFieldLocation) loc).getDeclaration();
275     if (decl != null)
276       return decl;
277       }
278     Object JavaDoc val = loc.get(null);
279     if (val != null)
280       return procToDecl(sym, val);
281     return null;
282   }
283
284   protected Expression walkReferenceExp (ReferenceExp exp)
285   {
286     return walkReferenceExp(exp, null);
287   }
288
289   protected Expression walkReferenceExp (ReferenceExp exp, ApplyExp call)
290   {
291     if (exp.getBinding() == null)
292       {
293     Object JavaDoc symbol = exp.getSymbol();
294         boolean function = exp.isProcedureName();
295         int namespace = call == null ? XQuery.VALUE_NAMESPACE
296           : XQuery.namespaceForFunctions(call.getArgCount());
297     Declaration decl = lookup.lookup(symbol, namespace);
298         Symbol sym;
299         if (decl != null)
300           ;
301     else if (symbol instanceof Symbol
302             && "".equals((sym = (Symbol) symbol).getNamespaceURI()))
303           {
304             // kludge - use xxx_BUILTIN mechanism? FIXME
305
String JavaDoc name = sym.getLocalName();
306             Expression f;
307             if ("request".equals(name))
308               f = XQParser.makeFunctionExp("gnu.kawa.servlet.GetRequest",
309                                            "getRequest");
310             else if ("response".equals(name))
311               f = XQParser.makeFunctionExp("gnu.kawa.servlet.GetResponse",
312                                            "getResponse");
313             else
314               f = null;
315             if (f != null)
316               return new ApplyExp(f, Expression.noExpressions);
317           }
318         else if (symbol instanceof Symbol)
319           {
320             // Never happens, I believe.
321
decl = flookup((Symbol) symbol);
322           }
323         else // if (symbol instanceof String)
324
{
325             String JavaDoc name = (String JavaDoc) symbol;
326             if (name.indexOf(':') < 0)
327               {
328                 name = name.intern();
329                 if (function)
330                   {
331                     for (int i = 0; i < functionNamespacePath.length; i++)
332                       {
333                         sym = functionNamespacePath[i].getSymbol(name);
334                         decl = lookup.lookup(sym, function);
335                         if (decl != null)
336                           break;
337                         if (! function)
338                           continue;
339                         decl = flookup(sym);
340                         if (decl != null)
341                           break;
342                       }
343                   }
344               }
345             if (decl == null)
346               {
347                 sym = parser.namespaceResolve(name, function);
348                 if (sym != null)
349                   {
350                     decl = lookup.lookup(sym, namespace);
351                     if (decl == null && function)
352                       {
353                         String JavaDoc uri = sym.getNamespaceURI();
354                         if (XQuery.SCHEMA_NAMESPACE.equals(uri))
355                           {
356                             Type type =
357                               XQuery.getStandardType(sym.getName());
358                             if (type != null)
359                               return QuoteExp.getInstance(type);
360                           }
361                         if (uri != null && uri.length() > 6 &&
362                             uri.startsWith("class:"))
363                           {
364                             ClassType ctype = ClassType.make(uri.substring(6));
365                             return GetNamedPart.makeExp(ctype, sym.getName());
366                           }
367                         decl = flookup(sym);
368                       }
369                   }
370               }
371           }
372         if (decl != null)
373           exp.setBinding(decl);
374         else if (function)
375           error('e', "unknown function "+symbol);
376         else
377           messages.error('e',"unknown variable $"+symbol, "XPST0008");
378       }
379     return exp;
380   }
381
382   protected Expression walkSetExp (SetExp exp)
383   {
384     Expression result = super.walkSetExp(exp);
385     Declaration decl = exp.getBinding();
386     Object JavaDoc name;
387     Expression new_value;
388     if (decl != null && ! getCompilation().immediate
389     && (name = decl.getSymbol()) instanceof Symbol
390     && XQuery.LOCAL_NAMESPACE.equals(((Symbol) name).getNamespaceURI())
391         && (! ((new_value = exp.getNewValue()) instanceof ApplyExp)
392             || ((ApplyExp) new_value).getFunction() != XQParser.getExternalFunction))
393       {
394     decl.setFlag(Declaration.PRIVATE_SPECIFIED);
395     decl.setPrivate(true);
396       }
397     return result;
398   }
399
400   private Declaration moduleDecl;
401   private Expression walkStatements (Expression exp)
402   {
403     // The tricky part here is interleaving declarations and statements
404
// so that a variable declaration is only visible *after* we have
405
// walked its initializing expression.
406
if (exp instanceof BeginExp)
407       {
408         BeginExp bbody = (BeginExp) exp;
409         Expression[] exps = bbody.getExpressions();
410         int nexps = bbody.getExpressionCount();
411         for (int i = 0; i < nexps; i++)
412           {
413             exps[i] = walkStatements(exps[i]);
414           }
415       }
416     else if (exp instanceof SetExp)
417       {
418         Declaration decl = moduleDecl;
419         while (decl != null && decl.isNamespaceDecl())
420           decl = decl.nextDecl();
421         SetExp sexp = (SetExp) exp;
422         exp = walkSetExp(sexp);
423         if (sexp.isDefining() && sexp.getBinding() == decl)
424           {
425             if (! decl.isProcedureDecl() && ! decl.isNamespaceDecl())
426               push(decl);
427             decl = decl.nextDecl();
428           }
429         moduleDecl = decl;
430       }
431     else
432       exp = walk(exp);
433     return exp;
434   }
435
436   public void resolveModule(ModuleExp exp)
437   {
438     currentLambda = exp;
439     for (Declaration decl = exp.firstDecl();
440          decl != null; decl = decl.nextDecl())
441       {
442         if (decl.isProcedureDecl())
443       push(decl);
444         else if (decl.isNamespaceDecl())
445           lookup.push(decl);
446       }
447     moduleDecl = exp.firstDecl();
448     exp.body = walkStatements(exp.body);
449
450     Expression[] exps;
451     if (currentDateTimeDecl != null)
452       {
453         // Some expression in this module calls one of the current-XXX
454
// functions, so calculate it and stash it, since these functions
455
// are required to be 'stable'.
456
// PROBLEM: We may get different results for calls in different
457
// modules. These functions should stash the current-dataTime in
458
// in the actual dynamic context. FIXME.
459
Vector JavaDoc vec = new Vector JavaDoc();
460         vec.addElement(new SetExp(currentDateTimeDecl,
461                                   new ApplyExp(ClassType.make("gnu.xquery.util.TimeUtils").getDeclaredMethod("now", 0),
462                                                Expression.noExpressions)));
463         Method cast = ClassType.make("gnu.math.DateTime").getDeclaredMethod("cast", 1);
464         if (currentDateDecl != null)
465           {
466             Expression[] args = { new ReferenceExp(currentDateTimeDecl),
467                                   new QuoteExp(IntNum.make(DateTime.DATE_MASK)) };
468             vec.addElement(new SetExp(currentDateDecl,
469                                       new ApplyExp(cast, args)));
470           }
471         if (currentTimeDecl != null)
472           {
473             Expression[] args = { new ReferenceExp(currentDateTimeDecl),
474                                   new QuoteExp(IntNum.make(DateTime.TIME_MASK)) };
475             vec.addElement(new SetExp(currentTimeDecl,
476                                       new ApplyExp(cast, args)));
477           }
478         if (currentTimezoneDecl != null)
479           {
480             Expression[] args = { new ReferenceExp(currentDateTimeDecl) };
481             vec.addElement(new SetExp(currentTimezoneDecl,
482                                       new ApplyExp(ClassType.make("gnu.xquery.util.TimeUtils").getDeclaredMethod("timezoneFromDateTime", 1), args)));
483           }
484         Expression body = exp.body;
485         if (body instanceof BeginExp)
486           {
487             BeginExp bexp = (BeginExp) body;
488             int blen = bexp.getExpressionCount();
489             exps = bexp.getExpressions();
490             for (int i = 0; i < blen; i++)
491               vec.addElement(exps[i]);
492           }
493         else
494           vec.addElement(body);
495         exps = new Expression[vec.size()];
496         vec.copyInto(exps);
497         exp.body = new BeginExp(exps);
498       }
499   }
500
501   /**
502    * Coerce argument to NamedCallator, or return default collator.
503    * @param args argument list
504    * @param argno index in args of collator argument
505    */

506   Expression getCollator (Expression[] args, int argno)
507   {
508     if (args != null && args.length > argno)
509       return new ApplyExp(ClassType.make("gnu.xquery.util.NamedCollator")
510                             .getDeclaredMethod("find", 1),
511                             new Expression[] { args[argno] });
512     NamedCollator coll = parser.defaultCollator;
513     return coll == null ? QuoteExp.nullExp : new QuoteExp(coll);
514   }
515
516   Expression withCollator (Method method, Expression[] args,
517                            String JavaDoc name, int minArgs)
518   {
519     return withCollator(new QuoteExp(new PrimProcedure(method)),
520                         args, name, minArgs);
521   }
522
523   /** Adjust call to add default collator if collator argument is missing. */
524   Expression withCollator (Expression function, Expression[] args,
525                            String JavaDoc name, int minArgs)
526   {
527     String JavaDoc err = WrongArguments.checkArgCount(name, minArgs, minArgs+1, args.length);
528     if (err != null)
529       return getCompilation().syntaxError(err);
530     Expression[] xargs = new Expression[minArgs+1];
531     System.arraycopy(args, 0, xargs, 0, minArgs);
532     xargs[minArgs] = getCollator(args, minArgs);
533     return new ApplyExp(function, xargs);
534   }
535
536   /** Adjust call to add default contex itemt if that argument is missing. */
537   Expression withContext (Method method, Expression[] args,
538                           String JavaDoc name, int minArgs)
539   {
540     String JavaDoc err = WrongArguments.checkArgCount(name, minArgs, minArgs+1,
541                                               args.length);
542     if (err != null)
543       return getCompilation().syntaxError(err);
544     if (args.length == minArgs)
545       {
546         Expression[] xargs = new Expression[minArgs+1];
547         System.arraycopy(args, 0, xargs, 0, minArgs);
548         Declaration dot = lookup.lookup(XQParser.DOT_VARNAME, false);
549         if (dot == null)
550           {
551             String JavaDoc message = "undefined context for " + name;
552             messages.error('e', message, "XPDY0002");
553             return new ErrorExp(message);
554           }
555         xargs[minArgs] = new ReferenceExp(dot);
556         args = xargs;
557       }
558     return new ApplyExp(method, args);
559   }
560
561   private Expression checkArgCount (Expression[] args, Declaration decl,
562                                     int min, int max)
563   {
564     String JavaDoc err = WrongArguments.checkArgCount("fn:"+decl.getName(),
565                                               min, max, args.length);
566     if (err == null)
567       return null;
568     else
569       return getCompilation().syntaxError(err);
570   }
571
572   protected Expression walkApplyExp (ApplyExp exp)
573   {
574     Expression func = exp.getFunction();
575     NamespaceBinding namespaceSave = parser.constructorNamespaces;
576     Object JavaDoc proc = exp.getFunctionValue();
577     if (proc instanceof MakeElement)
578       {
579         MakeElement mk = (MakeElement) proc;
580         NamespaceBinding nschain
581           = NamespaceBinding.nconc(mk.getNamespaceNodes(), namespaceSave);
582         mk.setNamespaceNodes(nschain);
583         parser.constructorNamespaces = nschain;
584       }
585     if (func instanceof ReferenceExp)
586       func = walkReferenceExp((ReferenceExp) func, exp);
587     else
588       func = walk(func);
589     exp.setFunction(func);
590     walkExps(exp.getArgs());
591     parser.constructorNamespaces = namespaceSave;
592     func = exp.getFunction();
593     if (func instanceof ReferenceExp)
594       {
595     Declaration decl = ((ReferenceExp) func).getBinding();
596     int code;
597         Expression err;
598         ModuleExp mexp;
599     if (decl != null && (code = decl.getCode()) < 0)
600       {
601         switch (code)
602           {
603           case POSITION_BUILTIN:
604           case LAST_BUILTIN:
605         Symbol sym = code == LAST_BUILTIN ? XQParser.LAST_VARNAME
606           : XQParser.POSITION_VARNAME;
607         decl = lookup.lookup(sym, false);
608         if (decl == null)
609           error('e', "undefined context for " + sym.getName());
610                 else
611                   // So ValuesFilter.inline can tell whether last() is used.
612
decl.setCanRead(true);
613         return new ReferenceExp(sym, decl);
614               case CAST_AS_BUILTIN:
615                 {
616           Expression[] args = exp.getArgs();
617                   if (args[0].valueIfConstant() == Compilation.typeSymbol)
618                     return walkApplyExp(XQParser.castQName(args[1]));
619                   func
620                     = XQParser.makeFunctionExp("gnu.xquery.util.CastAs", "castAs");
621                   return new ApplyExp(func, args);
622                 }
623               case CASTABLE_AS_BUILTIN:
624                 {
625           Expression[] args = exp.getArgs();
626                   if (args[1].valueIfConstant() == Compilation.typeSymbol
627                       && args[0] instanceof QuoteExp)
628                     {
629                       Object JavaDoc value = ((QuoteExp) args[0]).getValue();
630                       try
631                         {
632                           QNameUtils.resolveQName(value,
633                                                   parser.constructorNamespaces,
634                                                   parser.prologNamespaces);
635                           return XQuery.trueExp;
636                         }
637                       catch (RuntimeException JavaDoc ex)
638                         {
639                           return XQuery.falseExp;
640                         }
641                     }
642                   func = XQParser.makeFunctionExp("gnu.xquery.lang.XQParser", "castableAs");
643                   return new ApplyExp(func, args);
644                 }
645           case XS_QNAME_BUILTIN:
646         {
647           Expression[] args = exp.getArgs();
648                   if ((err = checkArgCount(args, decl, 1, 1)) != null)
649                     return err;
650           if (args[0] instanceof QuoteExp)
651             {
652               try
653             {
654               Object JavaDoc val = ((QuoteExp) args[0]).getValue();
655               val = QNameUtils.resolveQName(val,
656                                                         parser.constructorNamespaces,
657                                                         parser.prologNamespaces);
658               return new QuoteExp(val);
659             }
660               catch (RuntimeException JavaDoc ex)
661             {
662               return getCompilation().syntaxError(ex.getMessage());
663             }
664             }
665           Expression[] xargs = {
666             args[0],
667             new QuoteExp(parser.constructorNamespaces),
668             new QuoteExp(parser.prologNamespaces) };
669           Method meth
670             = (ClassType.make("gnu.xquery.util.QNameUtils")
671                .getDeclaredMethod("resolveQName", 3));
672           ApplyExp app = new ApplyExp(meth, xargs);
673           app.setFlag(ApplyExp.INLINE_IF_CONSTANT);
674           return app;
675         }
676           case RESOLVE_PREFIX_BUILTIN:
677         {
678           Expression[] args = exp.getArgs();
679                   if ((err = checkArgCount(args, decl, 1, 1)) != null)
680                     return err;
681           if (args[0] instanceof QuoteExp)
682             {
683                       Object JavaDoc val = ((QuoteExp) args[0]).getValue();
684                       String JavaDoc prefix = val == null ? null : val.toString();
685                       val = QNameUtils.lookupPrefix(prefix,
686                                                     parser.constructorNamespaces,
687                                                     parser.prologNamespaces);
688                       if (val == null)
689                         return getCompilation()
690                           .syntaxError("unknown namespace prefix '"
691                                        +prefix+"'");
692                       return new QuoteExp(val);
693             }
694           Expression[] xargs = {
695             args[0],
696             new QuoteExp(parser.constructorNamespaces),
697             new QuoteExp(parser.prologNamespaces) };
698           PrimProcedure pproc
699             = new PrimProcedure(ClassType.make("gnu.xquery.util.QNameUtils")
700                                         .getDeclaredMethod("resolvePrefix", 3));
701           ApplyExp app = new ApplyExp(pproc, xargs);
702           app.setFlag(ApplyExp.INLINE_IF_CONSTANT);
703           return app;
704         }
705               case LOCAL_NAME_BUILTIN:
706         {
707                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
708                     .getDeclaredMethod("localName", 1);
709                   return withContext(meth, exp.getArgs(), "fn:local-name", 0);
710                 }
711               case NAME_BUILTIN:
712         {
713                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
714                     .getDeclaredMethod("name", 1);
715                   return withContext(meth, exp.getArgs(), "fn:name", 0);
716                 }
717               case NUMBER_BUILTIN:
718         {
719                   Method meth = ClassType.make("gnu.xquery.util.NumberValue")
720                     .getDeclaredMethod("numberValue", 1);
721                   return withContext(meth, exp.getArgs(), "fn:number", 0);
722                 }
723               case ROOT_BUILTIN:
724         {
725                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
726                     .getDeclaredMethod("root", 1);
727                   return withContext(meth, exp.getArgs(), "fn:root", 0);
728                 }
729               case BASE_URI_BUILTIN:
730         {
731                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
732                     .getDeclaredMethod("baseUri", 1);
733                   return withContext(meth, exp.getArgs(), "fn:base-uri", 0);
734                 }
735               case LANG_BUILTIN:
736         {
737                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
738                     .getDeclaredMethod("lang", 2);
739                   return withContext(meth, exp.getArgs(), "fn:lang", 1);
740                 }
741               case ID_BUILTIN:
742         {
743                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
744                     .getDeclaredMethod("id$X", 3);
745                   return withContext(meth, exp.getArgs(), "fn:id", 1);
746                 }
747               case IDREF_BUILTIN:
748         {
749                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
750                     .getDeclaredMethod("idref", 2);
751                   return withContext(meth, exp.getArgs(), "fn:idref", 1);
752                 }
753
754               case STATIC_BASE_URI_BUILTIN:
755                 {
756           Expression[] args = exp.getArgs();
757                   if ((err = checkArgCount(args, decl, 0, 0)) != null)
758                     return err;
759                   return getBaseUriExpr();
760                 }
761               case NAMESPACE_URI_BUILTIN:
762         {
763                   Method meth = ClassType.make("gnu.xquery.util.NodeUtils")
764                     .getDeclaredMethod("namespaceURI", 1);
765                   return withContext(meth, exp.getArgs(),
766                                      "fn:namespace-uri", 0);
767                 }
768
769               case NORMALIZE_SPACE_BUILTIN:
770         {
771                   Method meth = ClassType.make("gnu.xquery.util.StringUtils")
772                     .getDeclaredMethod("normalizeSpace", 1);
773                   return withContext(meth, exp.getArgs(),
774                                      "fn:normalize-space", 0);
775                 }
776
777               case UNORDERED_BUILTIN:
778                 {
779           Expression[] args = exp.getArgs();
780                   if ((err = checkArgCount(args, decl, 1, 1)) != null)
781                     return err;
782                   return args[0];
783                 }
784
785               case COMPARE_BUILTIN:
786         {
787                   Method meth = ClassType.make("gnu.xquery.util.StringUtils")
788                     .getDeclaredMethod("compare", 3);
789                   return withCollator(meth, exp.getArgs(), "fn:compare", 2);
790                 }
791
792               case STRING_BUILTIN:
793                 return withContext(ClassType.make("gnu.xml.TextUtils")
794                                    .getDeclaredMethod("asString", 1),
795                                    exp.getArgs(), "fn:string", 0);
796
797               case INDEX_OF_BUILTIN:
798         {
799                   Method meth = ClassType.make("gnu.xquery.util.SequenceUtils")
800                     .getDeclaredMethod("indexOf$X", 4);
801                   return withCollator(meth, exp.getArgs(), "fn:index-of", 2);
802                 }
803               case COLLECTION_BUILTIN:
804                 {
805                   Expression[] args = exp.getArgs();
806                   ClassType cl = ClassType.make("gnu.xquery.util.NodeUtils");
807                   Method meth = cl.getDeclaredMethod("collection", 2);
808                   if ((err = checkArgCount(args, decl, 0, 1)) != null)
809                     return err;
810                   Expression base = getBaseUriExpr();
811                   Expression uri = args.length > 0 ? args[0]
812                     : QuoteExp.voidExp;
813                   ApplyExp aexp
814                     = new ApplyExp(meth, new Expression[]{ uri, base });
815                   if (code == DOC_BUILTIN)
816                     aexp.setType(NodeType.documentNodeTest);
817                   else
818                     aexp.setType(XDataType.booleanType);
819                   return aexp;
820                 }
821               case DOC_BUILTIN:
822               case DOC_AVAILABLE_BUILTIN:
823                 {
824                   Expression[] args = exp.getArgs();
825                   ClassType cl = ClassType.make("gnu.xquery.util.NodeUtils");
826                   String JavaDoc mname;
827                   if (code == DOC_BUILTIN)
828                     {
829                       mname = "docCached";
830                       if (parser.warnOldVersion
831                           && "document".equals(decl.getName()))
832                         getCompilation()
833                           .error('w', "replace 'document' by 'doc'");
834                     }
835                   else
836                     mname = "availableCached";
837                   Method meth = cl.getDeclaredMethod(mname, 2);
838                   if ((err = checkArgCount(args, decl, 1, 1)) != null)
839                     return err;
840                   Expression base = getBaseUriExpr();
841                   ApplyExp aexp
842                     = new ApplyExp(meth, new Expression[]{ args[0], base });
843                   if (code == DOC_BUILTIN)
844                     aexp.setType(NodeType.documentNodeTest);
845                   else
846                     aexp.setType(XDataType.booleanType);
847                   return aexp;
848                 }
849               case RESOLVE_URI_BUILTIN:
850                 {
851                   Expression[] args = exp.getArgs();
852                   if ((err = checkArgCount(args, decl, 1, 2)) != null)
853                     return err;
854                   Expression[] margs = new Expression[2];
855                   margs[0] = args[0];
856                   if (args.length == 1)
857                     margs[1] = getBaseUriExpr();
858                   else
859                     margs[1] = args[1];
860                   Method meth = ClassType.make("gnu.xquery.util.QNameUtils")
861                     .getDeclaredMethod("resolveURI", 2);
862                   return new ApplyExp(meth, margs);
863                 }
864               case DISTINCT_VALUES_BUILTIN:
865                 {
866                   Method meth = ClassType.make("gnu.xquery.util.DistinctValues")
867                     .getDeclaredMethod("distinctValues$X", 3);
868                   return withCollator(meth, exp.getArgs(),
869                                       "fn:distinct-values", 1);
870
871                 }
872               case DEEP_EQUAL_BUILTIN:
873                 {
874                   Method meth = ClassType.make("gnu.xquery.util.SequenceUtils")
875                     .getDeclaredMethod("deepEqual", 3);
876                   return withCollator(meth, exp.getArgs(),
877                                       "fn:deep-equal", 2);
878                 }
879               case MIN_BUILTIN:
880                 {
881                   Method meth = ClassType.make("gnu.xquery.util.MinMax")
882                     .getDeclaredMethod("min", 2);
883                   return withCollator(meth, exp.getArgs(),
884                                       "fn:min", 1);
885                 }
886               case MAX_BUILTIN:
887                 {
888                   Method meth = ClassType.make("gnu.xquery.util.MinMax")
889                     .getDeclaredMethod("max", 2);
890                   return withCollator(meth, exp.getArgs(),
891                                       "fn:max", 1);
892                 }
893               case DEFAULT_COLLATION_BUILTIN:
894                 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null)
895                   return err;
896                 NamedCollator coll = parser.defaultCollator;
897                 return QuoteExp.getInstance(coll != null ? coll.getName()
898                           : NamedCollator.UNICODE_CODEPOINT_COLLATION);
899               case CURRENT_DATETIME_BUILTIN:
900                 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null)
901                   return err;
902                 mexp = getCompilation().mainLambda;
903                 if (currentDateTimeDecl == null)
904                   currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType);
905                 return new ReferenceExp(currentDateTimeDecl);
906               case CURRENT_DATE_BUILTIN:
907                 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null)
908                   return err;
909                 mexp = getCompilation().mainLambda;
910                 if (currentDateTimeDecl == null)
911                   currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType);
912                 if (currentDateDecl == null)
913                   currentDateDecl = mexp.addDeclaration("date", XTimeType.dateType);
914                 return new ReferenceExp(currentDateDecl);
915               case CURRENT_TIME_BUILTIN:
916                 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null)
917                   return err;
918                 mexp = getCompilation().mainLambda;
919                 if (currentDateTimeDecl == null)
920                   currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType);
921                 if (currentTimeDecl == null)
922                   currentTimeDecl = mexp.addDeclaration("time", XTimeType.timeType);
923                 return new ReferenceExp(currentTimeDecl);
924               case IMPLICIT_TIMEZONE_BUILTIN:
925                 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null)
926                   return err;
927                 mexp = getCompilation().mainLambda;
928                 if (currentDateTimeDecl == null)
929                   currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType);
930                 if (currentTimezoneDecl == null)
931                   currentTimezoneDecl = mexp.addDeclaration("timezone", XTimeType.dayTimeDurationType);
932                 return new ReferenceExp(currentTimezoneDecl);
933               case HANDLE_EXTENSION_BUILTIN:
934                 {
935                   Compilation comp = getCompilation();
936                   Expression[] args = exp.getArgs();
937                   int i = 0;
938                   for (; i < args.length - 1; i += 2)
939                     {
940                       Expression pname = args[i];
941                       String JavaDoc qname = (String JavaDoc) ((QuoteExp) pname).getValue();
942                       Symbol psymbol = parser.namespaceResolve(qname, false);
943                       if (psymbol == null)
944                         ; // error emitted in namespaceResolve
945
else if (psymbol.getNamespaceURI().length() == 0)
946                         comp.error('e', "pragma name cannot be in the empty namespace");
947                       else
948                         {
949                           Expression replacement
950                             = checkPragma(psymbol, args[i+1]);
951                           if (replacement != null)
952                             return replacement;
953                         }
954                     }
955                   if (i < args.length)
956                     return args[args.length-1];
957                   String JavaDoc msg = "no recognized pragma or default in extension expression";
958                   getMessages().error('e', msg, "XQST0079");
959                   return new ErrorExp(msg);
960                 }
961           }
962       }
963       }
964     proc = exp.getFunctionValue();
965     if (proc instanceof Type)
966       {
967         Expression[] args = exp.getArgs();
968         if (args.length != 1)
969           {
970             messages.error('e', "type constructor requires a single argument");
971             return exp;
972           }
973         return new ApplyExp(XQParser.makeFunctionExp("gnu.xquery.util.CastAs", "castAs"),
974                             new Expression[] { exp.getFunction(), args[0] });
975       }
976     if (proc instanceof MakeElement)
977       {
978     MakeElement make = (MakeElement) proc;
979
980     // Add namespaces nodes that might be needed.
981
NamespaceBinding nsBindings = make.getNamespaceNodes();
982     nsBindings = maybeAddNamespace(MakeElement.getTagName(exp),
983                        nsBindings);
984     Expression[] args = exp.getArgs();
985         Symbol[] attrSyms = new Symbol[args.length];
986         int nattrSyms = 0;
987     for (int i = 0; i < args.length; i++)
988       {
989         Expression arg = args[i];
990         if (arg instanceof ApplyExp)
991           {
992         ApplyExp app = (ApplyExp) arg;
993         if (app.getFunction() == MakeAttribute.makeAttributeExp)
994                   {
995                     Symbol sym = MakeElement.getTagName(app);
996                     if (sym != null)
997                       {
998                         for (int j = 0; ; j++)
999                           {
1000                            if (j == nattrSyms)
1001                              {
1002                                attrSyms[nattrSyms++] = sym;
1003                                break;
1004                              }
1005                            if (sym.equals(attrSyms[j]))
1006                              {
1007                                getCompilation().setLine(app);
1008                                Symbol groupSym = MakeElement.getTagName(exp);
1009                                String JavaDoc groupName = groupSym == null ? null
1010                                  : groupSym.toString();
1011                                messages.error('e', XMLFilter.duplicateAttributeMessage(sym, groupName), "XQST0040");
1012                              }
1013                          }
1014                      }
1015                    nsBindings = maybeAddNamespace(sym, nsBindings);
1016                  }
1017          }
1018      }
1019    if (nsBindings != null)
1020      make.setNamespaceNodes(nsBindings);
1021      }
1022    return exp;
1023  }
1024
1025  public Expression
1026  checkPragma (Symbol name, Expression contents)
1027  {
1028    return null;
1029  }
1030
1031  Expression getBaseUriExpr ()
1032  {
1033    Compilation comp = getCompilation();
1034    String JavaDoc staticBaseUri = parser.getStaticBaseUri();
1035    if (staticBaseUri != null)
1036      return QuoteExp.getInstance(staticBaseUri);
1037    else
1038      return gnu.kawa.functions.GetModuleClass.getModuleClassURI(comp);
1039  }
1040
1041  static NamespaceBinding maybeAddNamespace(Symbol qname,
1042                        NamespaceBinding bindings)
1043  {
1044    if (qname == null) // Happens if prevously-reported unknown prefix.
1045
return bindings;
1046    String JavaDoc prefix = qname.getPrefix();
1047    String JavaDoc uri = qname.getNamespaceURI();
1048    return NamespaceBinding.maybeAdd(prefix == "" ? null : prefix,
1049                                     uri == "" ? null : uri,
1050                                     bindings);
1051  }
1052
1053  /** Wrap a (known) procedure value as a Declaration. */
1054  static Declaration procToDecl (Object JavaDoc symbol, Object JavaDoc val)
1055  {
1056    Declaration decl = new Declaration(symbol);
1057    decl.setProcedureDecl(true);
1058    decl.noteValue(new QuoteExp(val));
1059    decl.setFlag(Declaration.IS_CONSTANT);
1060    return decl;
1061  }
1062}
1063
Popular Tags