OW2 Consortium ops

Rev

Rev 11877 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
9969 ebruchez 1
/**
2
 *  Copyright (C) 2008 Orbeon, Inc.
3
 *
4
 *  This program is free software; you can redistribute it and/or modify it under the terms of the
5
 *  GNU Lesser General Public License as published by the Free Software Foundation; either version
6
 *  2.1 of the License, or (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9
 *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
 *  See the GNU Lesser General Public License for more details.
11
 *
12
 *  The full text of the license is available at http://www.gnu.org/copyleft/lesser.html
13
 */
14
package org.orbeon.oxf.processor.pipeline;
15
 
16
import org.orbeon.oxf.common.OXFException;
11877 ebruchez 17
import org.orbeon.oxf.processor.pipeline.functions.RewriteResourceURI;
9969 ebruchez 18
import org.orbeon.oxf.xforms.function.xxforms.XXFormsProperty;
19
import org.orbeon.saxon.expr.Expression;
20
import org.orbeon.saxon.expr.StaticProperty;
21
import org.orbeon.saxon.functions.*;
22
import org.orbeon.saxon.om.NamespaceConstant;
23
import org.orbeon.saxon.trans.XPathException;
24
import org.orbeon.saxon.type.ItemType;
25
import org.orbeon.saxon.type.Type;
11877 ebruchez 26
import org.orbeon.saxon.value.AtomicValue;
9969 ebruchez 27
import org.orbeon.saxon.value.SequenceType;
28
 
29
import java.util.HashMap;
30
import java.util.Map;
31
 
32
public class PipelineFunctionLibrary implements FunctionLibrary {
33
 
34
    private static final PipelineFunctionLibrary instance = new PipelineFunctionLibrary();
35
 
36
    public static PipelineFunctionLibrary instance() {
37
        return instance;
38
    }
39
 
40
    private static Map functionTable = new HashMap();
41
 
42
    private static StandardFunction.Entry register(String name,
43
                                                   Class implementationClass,
44
                                                   int opcode,
45
                                                   int minArguments,
46
                                                   int maxArguments,
47
                                                   ItemType itemType,
48
                                                   int cardinality) {
49
        StandardFunction.Entry e = new StandardFunction.Entry();
50
        e.name = name;
51
        e.implementationClass = implementationClass;
52
        e.opcode = opcode;
53
        e.minArguments = minArguments;
54
        e.maxArguments = maxArguments;
55
        e.itemType = itemType;
56
        e.cardinality = cardinality;
57
        e.argumentTypes = new SequenceType[maxArguments];
58
 
59
        functionTable.put(name, e);
60
        return e;
61
    }
62
 
10723 ebruchez 63
    // Functions are exposed statically below for access through XSLT
64
 
11877 ebruchez 65
    public static AtomicValue property(String name) {
10723 ebruchez 66
        return XXFormsProperty.property(name);
67
    }
68
 
69
    public static String rewriteResourceURI(String uri, boolean absolute) {
70
        return RewriteResourceURI.rewriteResourceURI(uri, absolute);
71
    }
72
 
9969 ebruchez 73
    static {
74
        StandardFunction.Entry e;
75
 
76
        // property() function
11877 ebruchez 77
        e = register("{" + PipelineProcessor.PIPELINE_NAMESPACE_URI + "}property", XXFormsProperty.class, 0, 1, 1, Type.ANY_ATOMIC_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
9969 ebruchez 78
        StandardFunction.arg(e, 0, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
79
 
10599 ebruchez 80
        // rewrite-resource-uri() function
81
        e = register("{" + PipelineProcessor.PIPELINE_NAMESPACE_URI + "}rewrite-resource-uri", RewriteResourceURI.class, 0, 1, 2, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
82
        StandardFunction.arg(e, 0, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
83
        StandardFunction.arg(e, 1, Type.BOOLEAN_TYPE, StaticProperty.EXACTLY_ONE);
84
 
9969 ebruchez 85
        // Useful XSLT function
86
        e = register("format-date", FormatDate.class, Type.DATE, 2, 5, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
87
        StandardFunction.arg(e, 0, Type.DATE_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
88
        StandardFunction.arg(e, 1, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
89
        StandardFunction.arg(e, 2, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
90
        StandardFunction.arg(e, 3, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
91
        StandardFunction.arg(e, 4, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
92
 
93
        e = register("format-dateTime", FormatDate.class, Type.DATE_TIME, 2, 5, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
94
        StandardFunction.arg(e, 0, Type.DATE_TIME_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
95
        StandardFunction.arg(e, 1, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
96
        StandardFunction.arg(e, 2, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
97
        StandardFunction.arg(e, 3, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
98
        StandardFunction.arg(e, 4, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
99
 
100
        e = register("format-number", FormatNumber2.class, 0, 2, 3, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
101
        StandardFunction.arg(e, 0, Type.NUMBER_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
102
        StandardFunction.arg(e, 1, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
103
        StandardFunction.arg(e, 2, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
104
 
105
        e = register("format-time", FormatDate.class, Type.TIME, 2, 5, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
106
        StandardFunction.arg(e, 0, Type.TIME_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
107
        StandardFunction.arg(e, 1, Type.STRING_TYPE, StaticProperty.EXACTLY_ONE);
108
        StandardFunction.arg(e, 2, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
109
        StandardFunction.arg(e, 3, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
110
        StandardFunction.arg(e, 4, Type.STRING_TYPE, StaticProperty.ALLOWS_ZERO_OR_ONE);
111
    }
112
 
113
    private StandardFunction.Entry getEntry(String uri, String local, int arity) {
114
        StandardFunction.Entry entry;
115
        if (uri.equals(NamespaceConstant.FN)) {
116
            entry = (StandardFunction.Entry) functionTable.get(local);
117
        } else if (uri.equals(PipelineProcessor.PIPELINE_NAMESPACE_URI)) {
118
            entry = (StandardFunction.Entry) functionTable.get("{" + uri + "}" + local);
119
        } else {
120
            return null;
121
        }
122
 
123
        if (entry == null || !(arity == -1 || arity >= entry.minArguments && arity <= entry.maxArguments)) {
124
            return null;
125
        }
126
 
127
        return entry;
128
    }
129
 
130
    public boolean isAvailable(int fingerprint, String uri, String local, int arity) {
131
        StandardFunction.Entry entry = getEntry(uri, local, arity);
132
        return entry != null;
133
    }
134
 
135
    public Expression bind(int nameCode, String uri, String local, Expression[] staticArgs) throws XPathException {
136
        StandardFunction.Entry entry = getEntry(uri, local, staticArgs.length);
137
        if (entry == null) {
138
            return null;
139
        }
140
 
141
        Class functionClass = entry.implementationClass;
142
        SystemFunction f;
143
        try {
144
            f = (SystemFunction) functionClass.newInstance();
145
        } catch (Exception err) {
146
            throw new OXFException("Failed to load function: " + err.getMessage(), err);
147
        }
148
        f.setDetails(entry);
149
        f.setFunctionNameCode(nameCode);
150
        f.setArguments(staticArgs);
151
        return f;
152
    }
153
 
154
    public FunctionLibrary copy() {
155
        return this;
156
    }
157
 
158
    public int hashCode() {
159
        // There is only one global function library, so we don't need a special hashCode() implementation
160
        return super.hashCode();
161
    }
162
}