001: package net.sf.saxon.om;
002:
003: import net.sf.saxon.trans.StaticError;
004: import net.sf.saxon.type.Type;
005:
006: /**
007: * An axis, that is a direction of navigation in the document structure.
008: */
009:
010: public final class Axis {
011:
012: /**
013: * Constant representing the ancestor axis
014: */
015:
016: public static final byte ANCESTOR = 0;
017: /** Constant representing the ancestor-or-self axis
018: */
019: public static final byte ANCESTOR_OR_SELF = 1;
020: /** Constant representing the attribute axis
021: */
022: public static final byte ATTRIBUTE = 2;
023: /** Constant representing the child axis
024: */
025: public static final byte CHILD = 3;
026: /** Constant representing the descendant axis
027: */
028: public static final byte DESCENDANT = 4;
029: /** Constant representing the descendant-or-self axis
030: */
031: public static final byte DESCENDANT_OR_SELF = 5;
032: /** Constant representing the following axis
033: */
034: public static final byte FOLLOWING = 6;
035: /** Constant representing the following-sibling axis
036: */
037: public static final byte FOLLOWING_SIBLING = 7;
038: /** Constant representing the namespace axis
039: */
040: public static final byte NAMESPACE = 8;
041: /** Constant representing the parent axis
042: */
043: public static final byte PARENT = 9;
044: /** Constant representing the preceding axis
045: */
046: public static final byte PRECEDING = 10;
047: /** Constant representing the preceding-sibling axis
048: */
049: public static final byte PRECEDING_SIBLING = 11;
050: /** Constant representing the self axis
051: */
052: public static final byte SELF = 12;
053:
054: // preceding-or-ancestor axis gives all preceding nodes including ancestors,
055: // in reverse document order
056:
057: /** Constant representing the preceding-or-ancestor axis. This axis is used internally by the xsl:number implementation, it returns the union of the preceding axis and the ancestor axis.
058: */
059: public static final byte PRECEDING_OR_ANCESTOR = 13;
060:
061: /**
062: * Table indicating the principal node type of each axis
063: */
064:
065: public static final short[] principalNodeType = { Type.ELEMENT, // ANCESTOR
066: Type.ELEMENT, // ANCESTOR_OR_SELF;
067: Type.ATTRIBUTE, // ATTRIBUTE;
068: Type.ELEMENT, // CHILD;
069: Type.ELEMENT, // DESCENDANT;
070: Type.ELEMENT, // DESCENDANT_OR_SELF;
071: Type.ELEMENT, // FOLLOWING;
072: Type.ELEMENT, // FOLLOWING_SIBLING;
073: Type.NAMESPACE, // NAMESPACE;
074: Type.ELEMENT, // PARENT;
075: Type.ELEMENT, // PRECEDING;
076: Type.ELEMENT, // PRECEDING_SIBLING;
077: Type.ELEMENT, // SELF;
078: Type.ELEMENT, // PRECEDING_OR_ANCESTOR;
079: };
080:
081: /**
082: * Table indicating for each axis whether it is in forwards document order
083: */
084:
085: public static final boolean[] isForwards = { false, // ANCESTOR
086: false, // ANCESTOR_OR_SELF;
087: true, // ATTRIBUTE;
088: true, // CHILD;
089: true, // DESCENDANT;
090: true, // DESCENDANT_OR_SELF;
091: true, // FOLLOWING;
092: true, // FOLLOWING_SIBLING;
093: false, // NAMESPACE;
094: true, // PARENT;
095: false, // PRECEDING;
096: false, // PRECEDING_SIBLING;
097: true, // SELF;
098: false, // PRECEDING_OR_ANCESTOR;
099: };
100:
101: /**
102: * Table indicating for each axis whether it is in reverse document order
103: */
104:
105: public static final boolean[] isReverse = { true, // ANCESTOR
106: true, // ANCESTOR_OR_SELF;
107: false, // ATTRIBUTE;
108: false, // CHILD;
109: false, // DESCENDANT;
110: false, // DESCENDANT_OR_SELF;
111: false, // FOLLOWING;
112: false, // FOLLOWING_SIBLING;
113: false, // NAMESPACE;
114: true, // PARENT;
115: true, // PRECEDING;
116: true, // PRECEDING_SIBLING;
117: true, // SELF;
118: true, // PRECEDING_OR_ANCESTOR;
119: };
120:
121: /**
122: * Table indicating for each axis whether it is a peer axis. An axis is a peer
123: * axis if no node on the axis is an ancestor of another node on the axis.
124: */
125:
126: public static final boolean[] isPeerAxis = { false, // ANCESTOR
127: false, // ANCESTOR_OR_SELF;
128: true, // ATTRIBUTE;
129: true, // CHILD;
130: false, // DESCENDANT;
131: false, // DESCENDANT_OR_SELF;
132: false, // FOLLOWING;
133: true, // FOLLOWING_SIBLING;
134: true, // NAMESPACE;
135: true, // PARENT;
136: false, // PRECEDING;
137: true, // PRECEDING_SIBLING;
138: true, // SELF;
139: false, // PRECEDING_OR_ANCESTOR;
140: };
141:
142: /**
143: * Table indicating for each axis whether it is contained within the subtree
144: * rooted at the origin node.
145: */
146:
147: public static final boolean[] isSubtreeAxis = { false, // ANCESTOR
148: false, // ANCESTOR_OR_SELF;
149: true, // ATTRIBUTE;
150: true, // CHILD;
151: true, // DESCENDANT;
152: true, // DESCENDANT_OR_SELF;
153: false, // FOLLOWING;
154: false, // FOLLOWING_SIBLING;
155: true, // NAMESPACE;
156: false, // PARENT;
157: false, // PRECEDING;
158: false, // PRECEDING_SIBLING;
159: true, // SELF;
160: false, // PRECEDING_OR_ANCESTOR;
161: };
162:
163: /**
164: * Table giving the name each axis
165: */
166:
167: public static final String[] axisName = { "ancestor", // ANCESTOR
168: "ancestor-or-self", // ANCESTOR_OR_SELF;
169: "attribute", // ATTRIBUTE;
170: "child", // CHILD;
171: "descendant", // DESCENDANT;
172: "descendant-or-self", // DESCENDANT_OR_SELF;
173: "following", // FOLLOWING;
174: "following-sibling", // FOLLOWING_SIBLING;
175: "namespace", // NAMESPACE;
176: "parent", // PARENT;
177: "preceding", // PRECEDING;
178: "preceding-sibling", // PRECEDING_SIBLING;
179: "self", // SELF;
180: "preceding-or-ancestor",// PRECEDING_OR_ANCESTOR;
181: };
182:
183: /**
184: * The class is never instantiated
185: */
186:
187: private Axis() {
188: }
189:
190: /**
191: * Resolve an axis name into a symbolic constant representing the axis
192: *
193: * @param name
194: * @exception net.sf.saxon.trans.StaticError
195: * @return integer value representing the named axis
196: */
197:
198: public static byte getAxisNumber(String name) throws StaticError {
199: if (name.equals("ancestor"))
200: return ANCESTOR;
201: if (name.equals("ancestor-or-self"))
202: return ANCESTOR_OR_SELF;
203: if (name.equals("attribute"))
204: return ATTRIBUTE;
205: if (name.equals("child"))
206: return CHILD;
207: if (name.equals("descendant"))
208: return DESCENDANT;
209: if (name.equals("descendant-or-self"))
210: return DESCENDANT_OR_SELF;
211: if (name.equals("following"))
212: return FOLLOWING;
213: if (name.equals("following-sibling"))
214: return FOLLOWING_SIBLING;
215: if (name.equals("namespace"))
216: return NAMESPACE;
217: if (name.equals("parent"))
218: return PARENT;
219: if (name.equals("preceding"))
220: return PRECEDING;
221: if (name.equals("preceding-sibling"))
222: return PRECEDING_SIBLING;
223: if (name.equals("self"))
224: return SELF;
225: // preceding-or-ancestor cannot be used in an XPath expression
226: throw new StaticError("Unknown axis name: " + name);
227: }
228:
229: /**
230: * The following table indicates the combinations of axis and node-kind that always
231: * return an empty result.
232: */
233:
234: private static final int DOC = 1 << Type.DOCUMENT;
235: private static final int ELE = 1 << Type.ELEMENT;
236: private static final int ATT = 1 << Type.ATTRIBUTE;
237: private static final int TEX = 1 << Type.TEXT;
238: private static final int PIN = 1 << Type.PROCESSING_INSTRUCTION;
239: private static final int COM = 1 << Type.COMMENT;
240: private static final int NAM = 1 << Type.NAMESPACE;
241:
242: private static int[] voidAxisTable = { DOC, // ANCESTOR
243: 0, // ANCESTOR_OR_SELF;
244: DOC | ATT | TEX | PIN | COM | NAM, // ATTRIBUTE;
245: ATT | TEX | PIN | COM | NAM, // CHILD;
246: ATT | TEX | PIN | COM | NAM, // DESCENDANT;
247: 0, // DESCENDANT_OR_SELF;
248: DOC, // FOLLOWING;
249: DOC | ATT | NAM, // FOLLOWING_SIBLING;
250: DOC | ATT | TEX | PIN | COM | NAM, // NAMESPACE;
251: DOC, // PARENT;
252: DOC, // PRECEDING;
253: DOC | ATT | NAM, // PRECEDING_SIBLING;
254: 0, // SELF;
255: };
256:
257: public static boolean isAlwaysEmpty(int axis, int nodeKind) {
258: return (voidAxisTable[axis] & (1 << nodeKind)) != 0;
259: }
260:
261: /**
262: * The following table indicates the kinds of node found on each axis
263: */
264:
265: private static int[] nodeKindTable = { DOC | ELE, // ANCESTOR
266: DOC | ELE | ATT | TEX | PIN | COM | NAM, // ANCESTOR_OR_SELF;
267: ATT, // ATTRIBUTE;
268: ELE | TEX | PIN | COM, // CHILD;
269: ELE | TEX | PIN | COM, // DESCENDANT;
270: DOC | ELE | ATT | TEX | PIN | COM | NAM, // DESCENDANT_OR_SELF;
271: ELE | TEX | PIN | COM, // FOLLOWING;
272: ELE | TEX | PIN | COM, // FOLLOWING_SIBLING;
273: NAM, // NAMESPACE;
274: DOC | ELE, // PARENT;
275: DOC | ELE | TEX | PIN | COM, // PRECEDING;
276: ELE | TEX | PIN | COM, // PRECEDING_SIBLING;
277: DOC | ELE | ATT | TEX | PIN | COM | NAM, // SELF;
278: };
279:
280: /**
281: * Determine whether a given kind of node can be found on a given axis
282: */
283:
284: public static boolean containsNodeKind(int axis, int nodeKind) {
285: return (nodeKindTable[axis] & (1 << nodeKind)) != 0;
286: }
287:
288: }
289:
290: /*
291: // a list for any future cut-and-pasting...
292: ANCESTOR
293: ANCESTOR_OR_SELF;
294: ATTRIBUTE;
295: CHILD;
296: DESCENDANT;
297: DESCENDANT_OR_SELF;
298: FOLLOWING;
299: FOLLOWING_SIBLING;
300: NAMESPACE;
301: PARENT;
302: PRECEDING;
303: PRECEDING_SIBLING;
304: SELF;
305: */
306:
307: //
308: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
309: // you may not use this file except in compliance with the License. You may obtain a copy of the
310: // License at http://www.mozilla.org/MPL/
311: //
312: // Software distributed under the License is distributed on an "AS IS" basis,
313: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
314: // See the License for the specific language governing rights and limitations under the License.
315: //
316: // The Original Code is: all this file.
317: //
318: // The Initial Developer of the Original Code is Michael H. Kay.
319: //
320: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
321: //
322: // Contributor(s): none.
323: //
|