001: // Copyright (c) 2001, 2002, 2003, 2006 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.lists.*;
008: import gnu.xml.*;
009: import gnu.expr.*;
010: import java.io.*;
011: import gnu.mapping.*;
012:
013: public class ElementType extends NodeType implements TypeValue,
014: Externalizable, ElementPredicate {
015: public static final String MATCH_ANY_LOCALNAME = "";
016: public static final Symbol MATCH_ANY_QNAME = new Symbol(null,
017: MATCH_ANY_LOCALNAME);
018:
019: Symbol qname;
020:
021: public static final ElementType anyElement = make(null, null);
022:
023: /** An element type for match by name.
024: * @param localName if null matches any local name; otherwise must
025: * be intered, and matches by identity.
026: * @param namespaceURI full name of namespace, or null for any namespace. */
027: public static ElementType make(String namespaceURI, String localName) {
028: Symbol qname;
029: if (namespaceURI != null)
030: qname = Symbol.make(namespaceURI, localName);
031: else if (localName == MATCH_ANY_LOCALNAME)
032: qname = MATCH_ANY_QNAME;
033: else
034: qname = new Symbol(null, localName);
035: return new ElementType(qname);
036: }
037:
038: public static ElementType make(Symbol qname) {
039: return new ElementType(qname);
040: }
041:
042: public ElementType(Symbol qname) {
043: this (null, qname);
044: }
045:
046: public ElementType(String name, Symbol qname) {
047: super (name != null && name.length() > 0 ? name : "ELEMENT "
048: + qname + " (*)");
049: this .qname = qname;
050: }
051:
052: public Type getImplementationType() {
053: return ClassType.make("gnu.kawa.xml.KElement");
054: }
055:
056: public final String getNamespaceURI() {
057: return qname.getNamespaceURI();
058: }
059:
060: public final String getLocalName() {
061: return qname.getLocalName();
062: }
063:
064: public void emitCoerceFromObject(CodeAttr code) {
065: code.emitPushString(qname.getNamespaceURI());
066: code.emitPushString(qname.getLocalName());
067: code.emitInvokeStatic(coerceMethod);
068: }
069:
070: public Object coerceFromObject(Object obj) {
071: return coerce(obj, qname.getNamespaceURI(), qname
072: .getLocalName());
073: }
074:
075: public boolean isInstancePos(AbstractSequence seq, int ipos) {
076: int kind = seq.getNextKind(ipos);
077: if (kind == Sequence.ELEMENT_VALUE)
078: return isInstance(seq, ipos, seq.getNextTypeObject(ipos));
079: if (kind == Sequence.OBJECT_VALUE)
080: return isInstance(seq.getPosNext(ipos));
081: return false;
082: }
083:
084: public boolean isInstance(AbstractSequence seq, int ipos,
085: Object elementType) {
086: String namespaceURI = qname.getNamespaceURI();
087: String localName = qname.getLocalName();
088: String curNamespaceURI;
089: String curLocalName;
090: if (elementType instanceof Symbol) {
091: Symbol qname = (Symbol) elementType;
092: curNamespaceURI = qname.getNamespaceURI();
093: curLocalName = qname.getLocalName();
094: }
095: /* #ifdef JAXP-1.3 */
096: // else if (elementType instanceof javax.xml.namespace.QName)
097: // {
098: // javax.xml.namespace.QName qtype
099: // = (javax.xml.namespace.QName) elementType;
100: // curNamespaceURI = qtype.getNamespaceURI();
101: // curLocalName = qtype.getLocalPart();
102: // }
103: /* #endif */
104: else {
105: curNamespaceURI = "";
106: curLocalName = elementType.toString().intern(); // FIXME
107: }
108: if (localName != null && localName.length() == 0)
109: localName = null;
110: return ((localName == curLocalName || localName == null) && (namespaceURI == curNamespaceURI || namespaceURI == null));
111: }
112:
113: public boolean isInstance(Object obj) {
114: return coerceOrNull(obj, qname.getNamespaceURI(), qname
115: .getLocalName()) != null;
116: }
117:
118: public static KElement coerceOrNull(Object obj,
119: String namespaceURI, String localName) {
120: KElement pos = (KElement) NodeType
121: .coerceOrNull(obj, ELEMENT_OK);
122: if (pos == null)
123: return null;
124: if (localName != null && localName.length() == 0)
125: localName = null;
126: //if (namespaceURI != null && namespaceURI.length() == 0)
127: // namespaceURI = null;
128: Object curName = pos.getNextTypeObject();
129: String curNamespaceURI;
130: String curLocalName;
131: if (curName instanceof Symbol) {
132: Symbol qname = (Symbol) curName;
133: curNamespaceURI = qname.getNamespaceURI();
134: curLocalName = qname.getLocalName();
135: }
136: /* #ifdef JAXP-1.3 */
137: // else if (curName instanceof javax.xml.namespace.QName)
138: // {
139: // javax.xml.namespace.QName qtype
140: // = (javax.xml.namespace.QName) curName;
141: // curNamespaceURI = qtype.getNamespaceURI();
142: // curLocalName = qtype.getLocalPart();
143: // }
144: /* #endif */
145: else {
146: curNamespaceURI = "";
147: curLocalName = curName.toString().intern(); // FIXME
148: }
149: if ((localName == curLocalName || localName == null)
150: && (namespaceURI == curNamespaceURI || namespaceURI == null))
151: return pos;
152: return null;
153: }
154:
155: public static KElement coerce(Object obj, String namespaceURI,
156: String localName) {
157: KElement pos = coerceOrNull(obj, namespaceURI, localName);
158: if (pos == null)
159: throw new ClassCastException();
160: return pos;
161: }
162:
163: protected void emitCoerceOrNullMethod(Variable incoming,
164: Compilation comp) {
165: CodeAttr code = comp.getCode();
166: if (incoming != null)
167: code.emitLoad(incoming);
168: code.emitPushString(qname.getNamespaceURI());
169: code.emitPushString(qname.getLocalName());
170: code.emitInvokeStatic(coerceOrNullMethod);
171: }
172:
173: NamespaceBinding namespaceNodes;
174:
175: public NamespaceBinding getNamespaceNodes() {
176: return namespaceNodes;
177: }
178:
179: public void setNamespaceNodes(NamespaceBinding bindings) {
180: namespaceNodes = bindings;
181: }
182:
183: public Procedure getConstructor() {
184: gnu.kawa.xml.MakeElement element = new gnu.kawa.xml.MakeElement();
185: element.tag = qname;
186: element.setHandlingKeywordParameters(true);
187: if (namespaceNodes != null)
188: element.setNamespaceNodes(namespaceNodes);
189: return element;
190: }
191:
192: public static final ClassType typeElementType = ClassType
193: .make("gnu.kawa.xml.ElementType");
194: static final Method coerceMethod = typeElementType
195: .getDeclaredMethod("coerce", 3);
196: static final Method coerceOrNullMethod = typeElementType
197: .getDeclaredMethod("coerceOrNull", 3);
198:
199: public void writeExternal(ObjectOutput out) throws IOException {
200: String name = getName();
201: out.writeUTF(name == null ? "" : name);
202: out.writeObject(qname);
203: }
204:
205: public void readExternal(ObjectInput in) throws IOException,
206: ClassNotFoundException {
207: String name = in.readUTF();
208: if (name.length() > 0)
209: setName(name);
210: qname = (Symbol) in.readObject();
211: }
212:
213: public String toString() {
214: return "ElementType " + qname;
215: }
216: }
|