001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.NamePool;
004: import net.sf.saxon.type.ItemType;
005:
006: import javax.xml.transform.SourceLocator;
007: import java.io.Serializable;
008:
009: /**
010: * A RoleLocator identifies the role in which an expression is used, for example as
011: * the third argument of the concat() function. This information is stored in an
012: * ItemChecker or CardinalityChecker so that good diagnostics can be
013: * achieved when run-time type errors are detected.
014: */
015: public class RoleLocator implements Serializable {
016:
017: private int kind;
018: private Object container;
019: private int operand;
020: private NamePool namePool;
021: private String errorCode = "XPTY0004"; // default error code for type errors
022: private SourceLocator sourceLocator;
023:
024: public static final int FUNCTION = 0;
025: public static final int BINARY_EXPR = 1;
026: public static final int TYPE_OP = 2;
027: public static final int VARIABLE = 3;
028: public static final int INSTRUCTION = 4;
029: public static final int FUNCTION_RESULT = 5;
030: public static final int ORDER_BY = 6;
031: public static final int TEMPLATE_RESULT = 7;
032:
033: /**
034: * Create information about the role of a subexpression within its parent expression
035: * @param kind the kind of parent expression, e.g. a function call or a variable reference
036: * @param container the name of the object in the parent expression, e.g. a function name or
037: * instruction name. May be expressed either as a String or as an Integer nameCode in the name pool.
038: * @param operand Ordinal position of this subexpression, e.g. the position of an argument in
039: * @param namePool The name pool. Must be supplied if the second argument is an Integer namecode.
040: * Otherwise, may be null.
041: */
042:
043: public RoleLocator(int kind, Object container, int operand,
044: NamePool namePool) {
045: this .kind = kind;
046: this .container = container;
047: this .operand = operand;
048: this .namePool = namePool;
049: }
050:
051: /**
052: * Set the error code to be produced if a type error is detected
053: * @param code The error code
054: */
055:
056: public void setErrorCode(String code) {
057: if (code != null) {
058: this .errorCode = code;
059: }
060: }
061:
062: /**
063: * Get the error code to be produced if a type error is detected
064: * @return code The error code
065: */
066:
067: public String getErrorCode() {
068: return errorCode;
069: }
070:
071: /**
072: * Set the source location
073: */
074:
075: public void setSourceLocator(SourceLocator locator) {
076: // this is currently used only when type-checking literals,
077: // which don't have any location information of their own
078: if (locator instanceof ExpressionLocation) {
079: this .sourceLocator = locator;
080: } else {
081: this .sourceLocator = new ExpressionLocation(locator);
082: }
083: // the supplied value isn't saved because the locator may be an expression that
084: // contains links back to the containing stylesheet, which causes the stylesheet
085: // to remain in memory at run-time (and prevents stylesheet compilation)
086: }
087:
088: /**
089: * Get the source location (if known - return null if not known)
090: */
091:
092: public SourceLocator getSourceLocator() {
093: return sourceLocator;
094: }
095:
096: /**
097: * Construct and return the error message indicating a type error
098: * @return the constructed error message
099: */
100: public String getMessage() {
101: String name;
102: if (container instanceof String) {
103: name = (String) container;
104: } else {
105: if (namePool == null) {
106: name = "*unknown*";
107: } else {
108: name = namePool.getDisplayName(((Integer) container)
109: .intValue());
110: }
111: }
112:
113: switch (kind) {
114: case FUNCTION:
115: return ordinal(operand + 1) + " argument of " + name + "()";
116: case BINARY_EXPR:
117: return ordinal(operand + 1) + " operand of '" + name + '\'';
118: case TYPE_OP:
119: return "value in '" + name + "' expression";
120: case VARIABLE:
121: return "value of variable $" + name;
122: case INSTRUCTION:
123: int slash = name.indexOf('/');
124: String attributeName = "";
125: if (slash >= 0) {
126: attributeName = name.substring(slash + 1);
127: name = name.substring(0, slash);
128: }
129: return '@' + attributeName + " attribute of " + name;
130: case FUNCTION_RESULT:
131: return "result of function " + name + "()";
132: case TEMPLATE_RESULT:
133: return "result of template " + name;
134: case ORDER_BY:
135: return ordinal(operand + 1) + " sort key";
136: default:
137: return "";
138: }
139: }
140:
141: /**
142: * Construct a full error message
143: */
144:
145: public String composeErrorMessage(ItemType requiredItemType,
146: ItemType suppliedItemType, NamePool pool) {
147: return "Required item type of " + getMessage() + " is "
148: + requiredItemType.toString(pool)
149: + "; supplied value has item type "
150: + suppliedItemType.toString(pool);
151: }
152:
153: /**
154: * Get the ordinal representation of a number (used to identify which argument of a function
155: * is in error)
156: * @param n the cardinal number
157: * @return the ordinal representation
158: */
159: private static String ordinal(int n) {
160: switch (n) {
161: case 1:
162: return "first";
163: case 2:
164: return "second";
165: case 3:
166: return "third";
167: default:
168: // we can live with 21th, 22th... How many functions have >20 arguments?
169: return n + "th";
170: }
171: }
172: }
173:
174: //
175: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
176: // you may not use this file except in compliance with the License. You may obtain a copy of the
177: // License at http://www.mozilla.org/MPL/
178: //
179: // Software distributed under the License is distributed on an "AS IS" basis,
180: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
181: // See the License for the specific language governing rights and limitations under the License.
182: //
183: // The Original Code is: all this file.
184: //
185: // The Initial Developer of the Original Code is Michael H. Kay.
186: //
187: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
188: //
189: // Contributor(s): none.
190: //
|