01: package gnu.xquery.util;
02:
03: import gnu.kawa.functions.Convert;
04: import gnu.bytecode.*;
05: import gnu.expr.*;
06: import gnu.kawa.xml.*;
07: import gnu.kawa.reflect.Invoke;
08: import gnu.kawa.reflect.OccurrenceType;
09: import gnu.mapping.Values;
10:
11: public class CastAs extends Convert {
12: public static final CastAs castAs = new CastAs();
13:
14: public Object apply2(Object arg1, Object arg2) {
15: Type type = (Type) arg1;
16: if (type instanceof XDataType)
17: return ((XDataType) type).cast(arg2);
18: if (type instanceof OccurrenceType) {
19: OccurrenceType occ = (OccurrenceType) type;
20: Type base = occ.getBase();
21: if (base instanceof XDataType) {
22: int min = occ.minOccurs();
23: int max = occ.maxOccurs();
24: if (arg2 instanceof Values) {
25: if (arg2 == Values.empty && min == 0)
26: return arg2;
27: Values vals = (Values) arg2;
28: int pos = vals.startPos();
29: int n = 0;
30: Values result = new Values();
31: for (;;) {
32: pos = vals.nextPos(pos);
33: if (pos == 0) {
34: if (n >= min && (max < 0 || n <= max))
35: return result.canonicalize();
36: break;
37: }
38: Object value = vals.getPosPrevious(pos);
39: value = ((XDataType) base).cast(value);
40: result.writeObject(value);
41: n++;
42: }
43: } else {
44: if (min <= 1 && max != 0)
45: return ((XDataType) base).cast(arg2);
46: }
47: throw new ClassCastException("cannot cast " + arg2
48: + " to " + arg1);
49: }
50: }
51: return super .apply2(arg1, arg2);
52: }
53:
54: static final ClassType typeXDataType = ClassType
55: .make("gnu.kawa.xml.XDataType");
56: static final Method castMethod = typeXDataType.getDeclaredMethod(
57: "cast", 1);
58:
59: public Expression inline(ApplyExp exp, ExpWalker walker) {
60: exp = Invoke.inlineClassName(exp, 0, (InlineCalls) walker);
61: Expression[] args = exp.getArgs();
62: if (args.length != 2 || !(args[0] instanceof QuoteExp))
63: return exp;
64: Object type = ((QuoteExp) args[0]).getValue();
65: if (type instanceof XDataType) {
66: XDataType xtype = (XDataType) type;
67: return new ApplyExp(castMethod, args);
68: }
69: return exp;
70: }
71:
72: public void compile(ApplyExp exp, Compilation comp, Target target) {
73: ApplyExp.compile(exp, comp, target);
74: }
75: }
|