001: // Copyright (c) 2003 Per M.A. Bothner.
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.Symbol;
012:
013: /** Matches an attribute name pattern.
014: * FIXME: ElementType and AttributeType should both inherit
015: * from a common NamedNodeType class. */
016:
017: public class AttributeType extends NodeType implements TypeValue,
018: Externalizable, AttributePredicate {
019: Symbol qname;
020:
021: public static AttributeType make(String namespaceURI,
022: String localName) {
023: Symbol qname;
024: if (namespaceURI != null)
025: qname = Symbol.make(namespaceURI, localName);
026: else if (localName == ElementType.MATCH_ANY_LOCALNAME)
027: qname = ElementType.MATCH_ANY_QNAME;
028: else
029: qname = new Symbol(null, localName);
030: return new AttributeType(qname);
031: }
032:
033: public static AttributeType make(Symbol qname) {
034: return new AttributeType(qname);
035: }
036:
037: public AttributeType(Symbol qname) {
038: this (null, qname);
039: }
040:
041: public AttributeType(String name, Symbol qname) {
042: super (name != null && name.length() > 0 ? name : "ATTRIBUTE "
043: + qname + " (*)");
044: this .qname = qname;
045: }
046:
047: public Type getImplementationType() {
048: return ClassType.make("gnu.kawa.xml.KAttr");
049: }
050:
051: public final String getNamespaceURI() {
052: return qname.getNamespaceURI();
053: }
054:
055: public final String getLocalName() {
056: return qname.getLocalName();
057: }
058:
059: public void emitCoerceFromObject(CodeAttr code) {
060: code.emitPushString(qname.getNamespaceURI());
061: code.emitPushString(qname.getLocalName());
062: code.emitInvokeStatic(coerceMethod);
063: }
064:
065: public Object coerceFromObject(Object obj) {
066: return coerce(obj, qname.getNamespaceURI(), qname
067: .getLocalName());
068: }
069:
070: public boolean isInstancePos(AbstractSequence seq, int ipos) {
071: int kind = seq.getNextKind(ipos);
072: if (kind == Sequence.ATTRIBUTE_VALUE)
073: return isInstance(seq, ipos, seq.getNextTypeObject(ipos));
074: if (kind == Sequence.OBJECT_VALUE)
075: return isInstance(seq.getPosNext(ipos));
076: return false;
077: }
078:
079: public boolean isInstance(AbstractSequence seq, int ipos,
080: Object attrType) {
081: String namespaceURI = qname.getNamespaceURI();
082: String localName = qname.getLocalName();
083: String curNamespaceURI;
084: String curLocalName;
085: if (attrType instanceof Symbol) {
086: Symbol qname = (Symbol) attrType;
087: curNamespaceURI = qname.getNamespaceURI();
088: curLocalName = qname.getLocalName();
089: }
090: /* #ifdef JAXP-1.3 */
091: // else if (attrType instanceof javax.xml.namespace.QName)
092: // {
093: // javax.xml.namespace.QName qtype
094: // = (javax.xml.namespace.QName) attrType;
095: // curNamespaceURI = qtype.getNamespaceURI();
096: // curLocalName = qtype.getLocalPart();
097: // }
098: /* #endif */
099: else {
100: curNamespaceURI = "";
101: curLocalName = attrType.toString().intern(); // FIXME
102: }
103: if (localName != null && localName.length() == 0)
104: localName = null;
105: return ((localName == curLocalName || localName == null) && (namespaceURI == curNamespaceURI || namespaceURI == null));
106: }
107:
108: public boolean isInstance(Object obj) {
109: return coerceOrNull(obj, qname.getNamespaceURI(), qname
110: .getLocalName()) != null;
111: }
112:
113: public static SeqPosition coerceOrNull(Object obj,
114: String namespaceURI, String localName) {
115: SeqPosition pos = NodeType.coerceOrNull(obj, ATTRIBUTE_OK);
116: if (pos == null)
117: return null;
118: if (localName != null && localName.length() == 0)
119: localName = null;
120: Object curName = pos.getNextTypeObject();
121: String curNamespaceURI;
122: String curLocalName;
123: if (curName instanceof Symbol) {
124: Symbol qname = (Symbol) curName;
125: curNamespaceURI = qname.getNamespaceURI();
126: curLocalName = qname.getLocalName();
127: }
128: /* #ifdef JAXP-1.3 */
129: // else if (curName instanceof javax.xml.namespace.QName)
130: // {
131: // javax.xml.namespace.QName qtype
132: // = (javax.xml.namespace.QName) curName;
133: // curNamespaceURI = qtype.getNamespaceURI();
134: // curLocalName = qtype.getLocalPart();
135: // }
136: /* #endif */
137: else {
138: curNamespaceURI = "";
139: curLocalName = curName.toString().intern(); // FIXME
140: }
141: if ((localName == curLocalName || localName == null)
142: && (namespaceURI == curNamespaceURI || namespaceURI == null))
143: return pos;
144: return null;
145: }
146:
147: public static SeqPosition coerce(Object obj, String namespaceURI,
148: String localName) {
149: SeqPosition pos = coerceOrNull(obj, namespaceURI, localName);
150: if (pos == null)
151: throw new ClassCastException();
152: return pos;
153: }
154:
155: protected void emitCoerceOrNullMethod(Variable incoming,
156: Compilation comp) {
157: CodeAttr code = comp.getCode();
158: if (incoming != null)
159: code.emitLoad(incoming);
160: code.emitPushString(qname.getNamespaceURI());
161: code.emitPushString(qname.getLocalName());
162: code.emitInvokeStatic(coerceOrNullMethod);
163: }
164:
165: public static final ClassType typeAttributeType = ClassType
166: .make("gnu.kawa.xml.AttributeType");
167: static final Method coerceMethod = typeAttributeType
168: .getDeclaredMethod("coerce", 3);
169: static final Method coerceOrNullMethod = typeAttributeType
170: .getDeclaredMethod("coerceOrNull", 3);
171:
172: public void writeExternal(ObjectOutput out) throws IOException {
173: String name = getName();
174: out.writeUTF(name == null ? "" : name);
175: out.writeObject(qname);
176: }
177:
178: public void readExternal(ObjectInput in) throws IOException,
179: ClassNotFoundException {
180: String name = in.readUTF();
181: if (name.length() > 0)
182: setName(name);
183: qname = (Symbol) in.readObject();
184: }
185:
186: public String toString() {
187: return "AttributeType " + qname;
188: }
189: }
|