001: // Copyright (c) 2001, 2003 Per M.A. Bothner and Brainfood Inc.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.xml;
005:
006: import gnu.bytecode.*;
007: import gnu.mapping.Procedure;
008: import gnu.lists.*;
009: import java.io.*;
010: import gnu.expr.*;
011: import gnu.xml.*;
012:
013: /** A SeqPosition used to represent a node in (usually) a TreeList.
014: * This is special in that the represented node is the current position
015: * of the SeqPosition - but when passed to a method it is only valid
016: * during that method. After the method returns, the caller is free to
017: * change the position, so if the node is saved in a data structure it
018: * must be copied. */
019:
020: public class NodeType extends ObjectType implements TypeValue,
021: NodePredicate, Externalizable {
022: public static final int TEXT_OK = 1;
023: public static final int ELEMENT_OK = 2;
024: public static final int ATTRIBUTE_OK = 4;
025: public static final int DOCUMENT_OK = 8;
026: public static final int COMMENT_OK = 16;
027: public static final int PI_OK = 32;
028: int kinds = -1;
029:
030: public NodeType(String name, int kinds) {
031: super (name);
032: this .kinds = kinds;
033: }
034:
035: public NodeType(String name) {
036: this (name, -1);
037: }
038:
039: public void emitCoerceFromObject(CodeAttr code) {
040: code.emitPushInt(kinds);
041: code.emitInvokeStatic(coerceMethod);
042: }
043:
044: public Object coerceFromObject(Object obj) {
045: return coerceForce(obj, kinds);
046: }
047:
048: public Type getImplementationType() {
049: return typeKNode;
050: }
051:
052: public int compare(Type other) {
053: return getImplementationType().compare(other);
054: }
055:
056: public boolean isInstance(Object obj) {
057: if (obj instanceof KNode) {
058: KNode pos = (KNode) obj;
059: return isInstancePos(pos.sequence, pos.getPos());
060: }
061: return false;
062: }
063:
064: public boolean isInstancePos(AbstractSequence seq, int ipos) {
065: return isInstance(seq, ipos, kinds);
066: }
067:
068: public static boolean isInstance(AbstractSequence seq, int ipos,
069: int kinds) {
070: int kind = seq.getNextKind(ipos);
071: if (kinds < 0)
072: return kind != Sequence.EOF_VALUE;
073: else {
074: switch (kind) {
075: case Sequence.EOF_VALUE:
076: return false;
077: case Sequence.INT_U8_VALUE:
078: case Sequence.INT_S8_VALUE:
079: case Sequence.INT_U16_VALUE:
080: case Sequence.INT_S16_VALUE:
081: case Sequence.INT_U32_VALUE:
082: case Sequence.INT_S32_VALUE:
083: case Sequence.INT_U64_VALUE:
084: case Sequence.INT_S64_VALUE:
085: case Sequence.FLOAT_VALUE:
086: case Sequence.DOUBLE_VALUE:
087: case Sequence.BOOLEAN_VALUE:
088: case Sequence.TEXT_BYTE_VALUE:
089: case Sequence.CHAR_VALUE:
090: case Sequence.OBJECT_VALUE:
091: return (kinds & TEXT_OK) != 0;
092: case Sequence.ELEMENT_VALUE:
093: return (kinds & ELEMENT_OK) != 0;
094: case Sequence.ATTRIBUTE_VALUE:
095: return (kinds & ATTRIBUTE_OK) != 0;
096: case Sequence.DOCUMENT_VALUE:
097: return (kinds & DOCUMENT_OK) != 0;
098: case Sequence.COMMENT_VALUE:
099: return (kinds & COMMENT_OK) != 0;
100: case Sequence.PROCESSING_INSTRUCTION_VALUE:
101: return (kinds & PI_OK) != 0;
102: }
103: }
104: return true;
105: }
106:
107: public static KNode coerceForce(Object obj, int kinds) {
108: KNode pos = coerceOrNull(obj, kinds);
109: if (pos == null)
110: throw new ClassCastException("coerce from "
111: + obj.getClass());
112: return pos;
113: }
114:
115: public static KNode coerceOrNull(Object obj, int kinds) {
116: KNode pos;
117: if (obj instanceof NodeTree)
118: pos = KNode.make((NodeTree) obj);
119: else if (obj instanceof KNode)
120: pos = (KNode) obj;
121: else
122: return null;
123: return isInstance(pos.sequence, pos.ipos, kinds) ? pos : null;
124: }
125:
126: protected void emitCoerceOrNullMethod(Variable incoming,
127: Compilation comp) {
128: CodeAttr code = comp.getCode();
129: if (incoming != null)
130: code.emitLoad(incoming);
131: code.emitPushInt(kinds);
132: code.emitInvokeStatic(coerceOrNullMethod);
133: }
134:
135: public void emitTestIf(Variable incoming, Declaration decl,
136: Compilation comp) {
137: CodeAttr code = comp.getCode();
138: emitCoerceOrNullMethod(incoming, comp);
139: if (decl != null) {
140: code.emitDup();
141: decl.compileStore(comp);
142: }
143: code.emitIfNotNull();
144: }
145:
146: public void emitIsInstance(Variable incoming, Compilation comp,
147: Target target) {
148: if (target instanceof ConditionalTarget) {
149: ConditionalTarget ctarget = (ConditionalTarget) target;
150: emitCoerceOrNullMethod(incoming, comp);
151: CodeAttr code = comp.getCode();
152: if (ctarget.trueBranchComesFirst)
153: code.emitGotoIfCompare1(ctarget.ifFalse, 198); // ifnull
154: else
155: code.emitGotoIfCompare1(ctarget.ifTrue, 199); // ifnonnull
156: ctarget.emitGotoFirstBranch(code);
157: } else
158: gnu.kawa.reflect.InstanceOf.emitIsInstance(this , incoming,
159: comp, target);
160: }
161:
162: public static final ClassType typeKNode = ClassType
163: .make("gnu.kawa.xml.KNode");
164: public static final ClassType typeNodeType = ClassType
165: .make("gnu.kawa.xml.NodeType");
166: public static final NodeType nodeType = new NodeType(
167: "gnu.kawa.xml.KNode");
168: static final Method coerceMethod = typeNodeType.getDeclaredMethod(
169: "coerceForce", 2);
170: static final Method coerceOrNullMethod = typeNodeType
171: .getDeclaredMethod("coerceOrNull", 2);
172:
173: public Procedure getConstructor() {
174: return null;
175: }
176:
177: public String toString() {
178: return "NodeType " + getName();
179: }
180:
181: public void writeExternal(ObjectOutput out) throws IOException {
182: String name = getName();
183: out.writeUTF(name == null ? "" : name);
184: out.writeInt(kinds);
185: }
186:
187: public void readExternal(ObjectInput in) throws IOException,
188: ClassNotFoundException {
189: String name = in.readUTF();
190: if (name.length() > 0)
191: setName(name);
192: kinds = in.readInt();
193: }
194:
195: public static final NodeType documentNodeTest = new NodeType(
196: "document-node", DOCUMENT_OK);
197: public static final NodeType textNodeTest = new NodeType("text",
198: TEXT_OK);
199: public static final NodeType commentNodeTest = new NodeType(
200: "comment", COMMENT_OK);
201: public static final NodeType anyNodeTest = new NodeType("node");
202: }
|