001: /*
002: * Copyright 1999-2005 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: /*
017: * $Id: FunctionTable.java,v 1.9 2005/05/17 21:25:46 jycli Exp $
018: */
019: package org.apache.xpath.compiler;
020:
021: import org.apache.xpath.Expression;
022: import org.apache.xpath.functions.Function;
023: import java.util.HashMap;
024: import javax.xml.transform.TransformerException;
025:
026: /**
027: * The function table for XPath.
028: */
029: public class FunctionTable {
030:
031: /** The 'current()' id. */
032: public static final int FUNC_CURRENT = 0;
033:
034: /** The 'last()' id. */
035: public static final int FUNC_LAST = 1;
036:
037: /** The 'position()' id. */
038: public static final int FUNC_POSITION = 2;
039:
040: /** The 'count()' id. */
041: public static final int FUNC_COUNT = 3;
042:
043: /** The 'id()' id. */
044: public static final int FUNC_ID = 4;
045:
046: /** The 'key()' id (XSLT). */
047: public static final int FUNC_KEY = 5;
048:
049: /** The 'local-name()' id. */
050: public static final int FUNC_LOCAL_PART = 7;
051:
052: /** The 'namespace-uri()' id. */
053: public static final int FUNC_NAMESPACE = 8;
054:
055: /** The 'name()' id. */
056: public static final int FUNC_QNAME = 9;
057:
058: /** The 'generate-id()' id. */
059: public static final int FUNC_GENERATE_ID = 10;
060:
061: /** The 'not()' id. */
062: public static final int FUNC_NOT = 11;
063:
064: /** The 'true()' id. */
065: public static final int FUNC_TRUE = 12;
066:
067: /** The 'false()' id. */
068: public static final int FUNC_FALSE = 13;
069:
070: /** The 'boolean()' id. */
071: public static final int FUNC_BOOLEAN = 14;
072:
073: /** The 'number()' id. */
074: public static final int FUNC_NUMBER = 15;
075:
076: /** The 'floor()' id. */
077: public static final int FUNC_FLOOR = 16;
078:
079: /** The 'ceiling()' id. */
080: public static final int FUNC_CEILING = 17;
081:
082: /** The 'round()' id. */
083: public static final int FUNC_ROUND = 18;
084:
085: /** The 'sum()' id. */
086: public static final int FUNC_SUM = 19;
087:
088: /** The 'string()' id. */
089: public static final int FUNC_STRING = 20;
090:
091: /** The 'starts-with()' id. */
092: public static final int FUNC_STARTS_WITH = 21;
093:
094: /** The 'contains()' id. */
095: public static final int FUNC_CONTAINS = 22;
096:
097: /** The 'substring-before()' id. */
098: public static final int FUNC_SUBSTRING_BEFORE = 23;
099:
100: /** The 'substring-after()' id. */
101: public static final int FUNC_SUBSTRING_AFTER = 24;
102:
103: /** The 'normalize-space()' id. */
104: public static final int FUNC_NORMALIZE_SPACE = 25;
105:
106: /** The 'translate()' id. */
107: public static final int FUNC_TRANSLATE = 26;
108:
109: /** The 'concat()' id. */
110: public static final int FUNC_CONCAT = 27;
111:
112: /** The 'substring()' id. */
113: public static final int FUNC_SUBSTRING = 29;
114:
115: /** The 'string-length()' id. */
116: public static final int FUNC_STRING_LENGTH = 30;
117:
118: /** The 'system-property()' id. */
119: public static final int FUNC_SYSTEM_PROPERTY = 31;
120:
121: /** The 'lang()' id. */
122: public static final int FUNC_LANG = 32;
123:
124: /** The 'function-available()' id (XSLT). */
125: public static final int FUNC_EXT_FUNCTION_AVAILABLE = 33;
126:
127: /** The 'element-available()' id (XSLT). */
128: public static final int FUNC_EXT_ELEM_AVAILABLE = 34;
129:
130: /** The 'unparsed-entity-uri()' id (XSLT). */
131: public static final int FUNC_UNPARSED_ENTITY_URI = 36;
132:
133: // Proprietary
134:
135: /** The 'document-location()' id (Proprietary). */
136: public static final int FUNC_DOCLOCATION = 35;
137:
138: /**
139: * The function table.
140: */
141: private static Class m_functions[];
142:
143: /** Table of function name to function ID associations. */
144: private static HashMap m_functionID = new HashMap();
145:
146: /**
147: * The function table contains customized functions
148: */
149: private Class m_functions_customer[] = new Class[NUM_ALLOWABLE_ADDINS];
150:
151: /**
152: * Table of function name to function ID associations for customized functions
153: */
154: private HashMap m_functionID_customer = new HashMap();
155:
156: /**
157: * Number of built in functions. Be sure to update this as
158: * built-in functions are added.
159: */
160: private static final int NUM_BUILT_IN_FUNCS = 37;
161:
162: /**
163: * Number of built-in functions that may be added.
164: */
165: private static final int NUM_ALLOWABLE_ADDINS = 30;
166:
167: /**
168: * The index to the next free function index.
169: */
170: private int m_funcNextFreeIndex = NUM_BUILT_IN_FUNCS;
171:
172: static {
173: m_functions = new Class[NUM_BUILT_IN_FUNCS];
174: m_functions[FUNC_CURRENT] = org.apache.xpath.functions.FuncCurrent.class;
175: m_functions[FUNC_LAST] = org.apache.xpath.functions.FuncLast.class;
176: m_functions[FUNC_POSITION] = org.apache.xpath.functions.FuncPosition.class;
177: m_functions[FUNC_COUNT] = org.apache.xpath.functions.FuncCount.class;
178: m_functions[FUNC_ID] = org.apache.xpath.functions.FuncId.class;
179: m_functions[FUNC_KEY] = org.apache.xalan.templates.FuncKey.class;
180: m_functions[FUNC_LOCAL_PART] = org.apache.xpath.functions.FuncLocalPart.class;
181: m_functions[FUNC_NAMESPACE] = org.apache.xpath.functions.FuncNamespace.class;
182: m_functions[FUNC_QNAME] = org.apache.xpath.functions.FuncQname.class;
183: m_functions[FUNC_GENERATE_ID] = org.apache.xpath.functions.FuncGenerateId.class;
184: m_functions[FUNC_NOT] = org.apache.xpath.functions.FuncNot.class;
185: m_functions[FUNC_TRUE] = org.apache.xpath.functions.FuncTrue.class;
186: m_functions[FUNC_FALSE] = org.apache.xpath.functions.FuncFalse.class;
187: m_functions[FUNC_BOOLEAN] = org.apache.xpath.functions.FuncBoolean.class;
188: m_functions[FUNC_LANG] = org.apache.xpath.functions.FuncLang.class;
189: m_functions[FUNC_NUMBER] = org.apache.xpath.functions.FuncNumber.class;
190: m_functions[FUNC_FLOOR] = org.apache.xpath.functions.FuncFloor.class;
191: m_functions[FUNC_CEILING] = org.apache.xpath.functions.FuncCeiling.class;
192: m_functions[FUNC_ROUND] = org.apache.xpath.functions.FuncRound.class;
193: m_functions[FUNC_SUM] = org.apache.xpath.functions.FuncSum.class;
194: m_functions[FUNC_STRING] = org.apache.xpath.functions.FuncString.class;
195: m_functions[FUNC_STARTS_WITH] = org.apache.xpath.functions.FuncStartsWith.class;
196: m_functions[FUNC_CONTAINS] = org.apache.xpath.functions.FuncContains.class;
197: m_functions[FUNC_SUBSTRING_BEFORE] = org.apache.xpath.functions.FuncSubstringBefore.class;
198: m_functions[FUNC_SUBSTRING_AFTER] = org.apache.xpath.functions.FuncSubstringAfter.class;
199: m_functions[FUNC_NORMALIZE_SPACE] = org.apache.xpath.functions.FuncNormalizeSpace.class;
200: m_functions[FUNC_TRANSLATE] = org.apache.xpath.functions.FuncTranslate.class;
201: m_functions[FUNC_CONCAT] = org.apache.xpath.functions.FuncConcat.class;
202: m_functions[FUNC_SYSTEM_PROPERTY] = org.apache.xpath.functions.FuncSystemProperty.class;
203: m_functions[FUNC_EXT_FUNCTION_AVAILABLE] = org.apache.xpath.functions.FuncExtFunctionAvailable.class;
204: m_functions[FUNC_EXT_ELEM_AVAILABLE] = org.apache.xpath.functions.FuncExtElementAvailable.class;
205: m_functions[FUNC_SUBSTRING] = org.apache.xpath.functions.FuncSubstring.class;
206: m_functions[FUNC_STRING_LENGTH] = org.apache.xpath.functions.FuncStringLength.class;
207: m_functions[FUNC_DOCLOCATION] = org.apache.xpath.functions.FuncDoclocation.class;
208: m_functions[FUNC_UNPARSED_ENTITY_URI] = org.apache.xpath.functions.FuncUnparsedEntityURI.class;
209: }
210:
211: static {
212: m_functionID.put(Keywords.FUNC_CURRENT_STRING, new Integer(
213: FunctionTable.FUNC_CURRENT));
214: m_functionID.put(Keywords.FUNC_LAST_STRING, new Integer(
215: FunctionTable.FUNC_LAST));
216: m_functionID.put(Keywords.FUNC_POSITION_STRING, new Integer(
217: FunctionTable.FUNC_POSITION));
218: m_functionID.put(Keywords.FUNC_COUNT_STRING, new Integer(
219: FunctionTable.FUNC_COUNT));
220: m_functionID.put(Keywords.FUNC_ID_STRING, new Integer(
221: FunctionTable.FUNC_ID));
222: m_functionID.put(Keywords.FUNC_KEY_STRING, new Integer(
223: FunctionTable.FUNC_KEY));
224: m_functionID.put(Keywords.FUNC_LOCAL_PART_STRING, new Integer(
225: FunctionTable.FUNC_LOCAL_PART));
226: m_functionID.put(Keywords.FUNC_NAMESPACE_STRING, new Integer(
227: FunctionTable.FUNC_NAMESPACE));
228: m_functionID.put(Keywords.FUNC_NAME_STRING, new Integer(
229: FunctionTable.FUNC_QNAME));
230: m_functionID.put(Keywords.FUNC_GENERATE_ID_STRING, new Integer(
231: FunctionTable.FUNC_GENERATE_ID));
232: m_functionID.put(Keywords.FUNC_NOT_STRING, new Integer(
233: FunctionTable.FUNC_NOT));
234: m_functionID.put(Keywords.FUNC_TRUE_STRING, new Integer(
235: FunctionTable.FUNC_TRUE));
236: m_functionID.put(Keywords.FUNC_FALSE_STRING, new Integer(
237: FunctionTable.FUNC_FALSE));
238: m_functionID.put(Keywords.FUNC_BOOLEAN_STRING, new Integer(
239: FunctionTable.FUNC_BOOLEAN));
240: m_functionID.put(Keywords.FUNC_LANG_STRING, new Integer(
241: FunctionTable.FUNC_LANG));
242: m_functionID.put(Keywords.FUNC_NUMBER_STRING, new Integer(
243: FunctionTable.FUNC_NUMBER));
244: m_functionID.put(Keywords.FUNC_FLOOR_STRING, new Integer(
245: FunctionTable.FUNC_FLOOR));
246: m_functionID.put(Keywords.FUNC_CEILING_STRING, new Integer(
247: FunctionTable.FUNC_CEILING));
248: m_functionID.put(Keywords.FUNC_ROUND_STRING, new Integer(
249: FunctionTable.FUNC_ROUND));
250: m_functionID.put(Keywords.FUNC_SUM_STRING, new Integer(
251: FunctionTable.FUNC_SUM));
252: m_functionID.put(Keywords.FUNC_STRING_STRING, new Integer(
253: FunctionTable.FUNC_STRING));
254: m_functionID.put(Keywords.FUNC_STARTS_WITH_STRING, new Integer(
255: FunctionTable.FUNC_STARTS_WITH));
256: m_functionID.put(Keywords.FUNC_CONTAINS_STRING, new Integer(
257: FunctionTable.FUNC_CONTAINS));
258: m_functionID.put(Keywords.FUNC_SUBSTRING_BEFORE_STRING,
259: new Integer(FunctionTable.FUNC_SUBSTRING_BEFORE));
260: m_functionID.put(Keywords.FUNC_SUBSTRING_AFTER_STRING,
261: new Integer(FunctionTable.FUNC_SUBSTRING_AFTER));
262: m_functionID.put(Keywords.FUNC_NORMALIZE_SPACE_STRING,
263: new Integer(FunctionTable.FUNC_NORMALIZE_SPACE));
264: m_functionID.put(Keywords.FUNC_TRANSLATE_STRING, new Integer(
265: FunctionTable.FUNC_TRANSLATE));
266: m_functionID.put(Keywords.FUNC_CONCAT_STRING, new Integer(
267: FunctionTable.FUNC_CONCAT));
268: m_functionID.put(Keywords.FUNC_SYSTEM_PROPERTY_STRING,
269: new Integer(FunctionTable.FUNC_SYSTEM_PROPERTY));
270: m_functionID.put(Keywords.FUNC_EXT_FUNCTION_AVAILABLE_STRING,
271: new Integer(FunctionTable.FUNC_EXT_FUNCTION_AVAILABLE));
272: m_functionID.put(Keywords.FUNC_EXT_ELEM_AVAILABLE_STRING,
273: new Integer(FunctionTable.FUNC_EXT_ELEM_AVAILABLE));
274: m_functionID.put(Keywords.FUNC_SUBSTRING_STRING, new Integer(
275: FunctionTable.FUNC_SUBSTRING));
276: m_functionID.put(Keywords.FUNC_STRING_LENGTH_STRING,
277: new Integer(FunctionTable.FUNC_STRING_LENGTH));
278: m_functionID.put(Keywords.FUNC_UNPARSED_ENTITY_URI_STRING,
279: new Integer(FunctionTable.FUNC_UNPARSED_ENTITY_URI));
280: m_functionID.put(Keywords.FUNC_DOCLOCATION_STRING, new Integer(
281: FunctionTable.FUNC_DOCLOCATION));
282: }
283:
284: public FunctionTable() {
285: }
286:
287: /**
288: * Return the name of the a function in the static table. Needed to avoid
289: * making the table publicly available.
290: */
291: String getFunctionName(int funcID) {
292: if (funcID < NUM_BUILT_IN_FUNCS)
293: return m_functions[funcID].getName();
294: else
295: return m_functions_customer[funcID - NUM_BUILT_IN_FUNCS]
296: .getName();
297: }
298:
299: /**
300: * Obtain a new Function object from a function ID.
301: *
302: * @param which The function ID, which may correspond to one of the FUNC_XXX
303: * values found in {@link org.apache.xpath.compiler.FunctionTable}, but may
304: * be a value installed by an external module.
305: *
306: * @return a a new Function instance.
307: *
308: * @throws javax.xml.transform.TransformerException if ClassNotFoundException,
309: * IllegalAccessException, or InstantiationException is thrown.
310: */
311: Function getFunction(int which)
312: throws javax.xml.transform.TransformerException {
313: try {
314: if (which < NUM_BUILT_IN_FUNCS)
315: return (Function) m_functions[which].newInstance();
316: else
317: return (Function) m_functions_customer[which
318: - NUM_BUILT_IN_FUNCS].newInstance();
319: } catch (IllegalAccessException ex) {
320: throw new TransformerException(ex.getMessage());
321: } catch (InstantiationException ex) {
322: throw new TransformerException(ex.getMessage());
323: }
324: }
325:
326: /**
327: * Obtain a function ID from a given function name
328: * @param key the function name in a java.lang.String format.
329: * @return a function ID, which may correspond to one of the FUNC_XXX values
330: * found in {@link org.apache.xpath.compiler.FunctionTable}, but may be a
331: * value installed by an external module.
332: */
333: Object getFunctionID(String key) {
334: Object id = m_functionID_customer.get(key);
335: if (null == id)
336: id = m_functionID.get(key);
337: return id;
338: }
339:
340: /**
341: * Install a built-in function.
342: * @param name The unqualified name of the function, must not be null
343: * @param func A Implementation of an XPath Function object.
344: * @return the position of the function in the internal index.
345: */
346: public int installFunction(String name, Class func) {
347:
348: int funcIndex;
349: Object funcIndexObj = getFunctionID(name);
350:
351: if (null != funcIndexObj) {
352: funcIndex = ((Integer) funcIndexObj).intValue();
353:
354: if (funcIndex < NUM_BUILT_IN_FUNCS) {
355: funcIndex = m_funcNextFreeIndex++;
356: m_functionID_customer.put(name, new Integer(funcIndex));
357: }
358: m_functions_customer[funcIndex - NUM_BUILT_IN_FUNCS] = func;
359: } else {
360: funcIndex = m_funcNextFreeIndex++;
361:
362: m_functions_customer[funcIndex - NUM_BUILT_IN_FUNCS] = func;
363:
364: m_functionID_customer.put(name, new Integer(funcIndex));
365: }
366: return funcIndex;
367: }
368:
369: /**
370: * Tell if a built-in, non-namespaced function is available.
371: *
372: * @param methName The local name of the function.
373: *
374: * @return True if the function can be executed.
375: */
376: public boolean functionAvailable(String methName) {
377: Object tblEntry = m_functionID.get(methName);
378: if (null != tblEntry)
379: return true;
380: else {
381: tblEntry = m_functionID_customer.get(methName);
382: return (null != tblEntry) ? true : false;
383: }
384: }
385: }
|