#!/usr/bin/python # Interim code generation script. import sys, os, mllib from cStringIO import StringIO out_dir=sys.argv[1] out_pkg = sys.argv[2] spec_file = sys.argv[3] spec = mllib.xml_parse(spec_file) class Output: def __init__(self, dir, package, name): self.dir = dir self.package = package self.name = name self.lines = [] self.line("package %s;" % self.package) self.line() self.line("import java.util.Map;") self.line("import java.util.UUID;") self.line() self.line() def line(self, l = ""): self.lines.append(l) def write(self): dir = os.path.join(self.dir, *self.package.split(".")) if not os.path.exists(dir): os.makedirs(dir) file = os.path.join(dir, "%s.java" % self.name) out = open(file, "w") for l in self.lines: out.write(l) out.write(os.linesep) out.close() TYPES = { "longstr": "String", "shortstr": "String", "longlong": "long", "long": "long", "short": "int", "octet": "short", "bit": "boolean", "table": "Map", "timestamp": "long", "content": "String", "uuid": "UUID", "rfc1982-long-set": "RangeSet", "long-struct": "Struct" } TRACKS = { "connection": "Frame.L1", "session": "Frame.L2", "execution": "Frame.L3", None: None } def camel(offset, *args): parts = [] for a in args: parts.extend(a.split("-")) return "".join(parts[:offset] + [p[0].upper() + p[1:] for p in parts[offset:]]) def dromedary(s): return s[0].lower() + s[1:] def scream(*args): return "_".join([a.replace("-", "_").upper() for a in args]) DOMAINS = {} STRUCTS = {} EXCLUDE = {"access-ticket": True} for d in spec.query["amqp/domain"]: name = d["@name"] type = d["@type"] if type != None: DOMAINS[name] = d["@type"] elif d["struct"] != None: DOMAINS[name] = name STRUCTS[name] = camel(0, name) def resolve(type): if DOMAINS.has_key(type) and DOMAINS[type] != type: return resolve(DOMAINS[type]) else: return type def jtype(type): if STRUCTS.has_key(type): return STRUCTS[type] else: return TYPES[type] OPTIONS = {} class Struct: def __init__(self, node, name, base, type, track, content): self.node = node self.name = name self.base = base self.type = type self.track = track self.content = content self.fields = [] def result(self): r = self.node["result"] if not r: return name = r["@domain"] if not name: name = self.name + "Result" else: name = camel(0, name) return name def field(self, type, name): self.fields.append((type, name)) def impl(self, out): out.line("public class %s extends %s {" % (self.name, self.base)) if self.type != None: out.line() out.line(" public static final int TYPE = %d;" % self.type) out.line() out.line(" public int getEncodedType() {") if self.type == None: out.line(" throw new UnsupportedOperationException();") else: out.line(" return TYPE;") out.line(" }") if self.base == "Method": out.line() out.line(" public boolean hasPayload() {") if self.content: out.line(" return true;") else: out.line(" return false;") out.line(" }") out.line() out.line(" public byte getEncodedTrack() {") out.line(" return %s;" % self.track) out.line(" }") out.line() for type, name in self.fields: out.line(" private %s %s;" % (jtype(type), name)) if self.fields: out.line() out.line(" public %s() {}" % self.name) out.line() out.line(" public %s(%s) {" % (self.name, self.parameters())) opts = False for type, name in self.fields: if not OPTIONS.has_key(name): out.line(" this.%s = %s;" % (name, name)) else: opts = True if opts: for type, name in self.fields: if OPTIONS.has_key(name): out.line(" boolean _%s = false;" % name) out.line(" for (int i=0; i < _options.length; i++) {") out.line(" switch (_options[i]) {") for type, name in self.fields: if OPTIONS.has_key(name): out.line(" case %s: _%s=true; break;" % (OPTIONS[name], name)) out.line(" case NO_OPTION: break;") out.line(' default: throw new IllegalArgumentException' '("invalid option: " + _options[i]);') out.line(" }") out.line(" }") for type, name in self.fields: if OPTIONS.has_key(name): out.line(" this.%s = _%s;" % (name, name)) out.line(" }") out.line() out.line(" public void delegate(C context, Delegate delegate) {") out.line(" delegate.%s(context, this);" % dromedary(self.name)) out.line(" }") for type, name in self.fields: out.line() out.line(" public %s %s() {" % (jtype(type), camel(1, "get", name))) out.line(" return %s;" % name) out.line(" }") out.line(" public %s %s(%s value) {" % (self.name, camel(1, "set", name), jtype(type))) out.line(" this.%s = value;" % name); out.line(" return this;") out.line(" }") out.line(" public %s %s(%s value) {" % (self.name, name, jtype(type))) out.line(" this.%s = value;" % name); out.line(" return this;") out.line(" }") out.line() out.line(" public void read(Decoder dec, byte major, byte minor) {") for type, name in self.fields: if TYPES.has_key(type): out.line(" %s = dec.read%s();" % (name, camel(0, type))) elif STRUCTS.has_key(type): out.line(" %s = new %s();" % (name, STRUCTS[type])) out.line(" %s.read(dec, major, minor);" % name) else: raise Exception("unknown type: %s" % type) out.line(" }") out.line() out.line(" public void write(Encoder enc, byte major, byte minor) {") for type, name in self.fields: if TYPES.has_key(type): out.line(" enc.write%s(%s);" % (camel(0, type), name)) elif STRUCTS.has_key(type): out.line(" if (%s == null) {" % name) out.line(" new %s().write(enc, major, minor);" % jtype(type)) out.line(" } else {") out.line(" %s.write(enc, major, minor);" % name) out.line(" }") else: raise Exception("unknown type: %s" % type) out.line(" }") out.line("}") def parameters(self): params = [] var = False for type, name in self.fields: if OPTIONS.has_key(name): var = True else: params.append("%s %s" % (jtype(type), name)) if var: params.append("Option ... _options") return ", ".join(params) def arguments(self): args = [] var = False for type, name in self.fields: if OPTIONS.has_key(name): var = True else: args.append(name) if var: args.append("_options") return ", ".join(args) CLASSES = {"file": False, "basic": False, "stream": False, "tunnel": False} FIELDS = {"ticket": False} class Visitor(mllib.transforms.Visitor): def __init__(self): self.structs = [] def do_method(self, m): if CLASSES.get(m.parent["@name"], True): name = camel(0, m.parent["@name"], m["@name"]) type = int(m.parent["@index"])*256 + int(m["@index"]) self.structs.append((name, "Method", type, m)) self.descend(m) def do_domain(self, d): s = d["struct"] if s: name = camel(0, d["@name"]) st = s["@type"] if st in (None, "none", ""): type = None else: type = int(st) self.structs.append((name, "Struct", type, s)) self.descend(d) def do_result(self, r): s = r["struct"] if s: name = camel(0, r.parent.parent["@name"], r.parent["@name"], "Result") type = int(r.parent.parent["@index"]) * 256 + int(s["@type"]) self.structs.append((name, "Result", type, s)) self.descend(r) v = Visitor() spec.dispatch(v) opts = Output(out_dir, out_pkg, "Option") opts.line("public enum Option {") structs = [] for name, base, typecode, m in v.structs: struct = Struct(m, name, base, typecode, TRACKS.get(m.parent["@name"], "Frame.L4"), m["@content"] == "1") for f in m.query["field", lambda f: FIELDS.get(f["@name"], True)]: type = resolve(f["@domain"]) name = camel(1, f["@name"]) struct.field(type, name) if type == "bit": opt_name = scream(f["@name"]) if not OPTIONS.has_key(name): OPTIONS[name] = opt_name opts.line(" %s," % opt_name) structs.append(struct) opts.line(" %s," % "NO_OPTION") opts.line("}") opts.write() for s in structs: impl = Output(out_dir, out_pkg, s.name) s.impl(impl) impl.write() fct = Output(out_dir, out_pkg, "StructFactory") fct.line("class StructFactory {") fct.line(" public static Struct create(int type) {") fct.line(" switch (type) {") for s in structs: if s.type == None: continue fct.line(" case %s.TYPE:" % s.name) fct.line(" return new %s();" % s.name) fct.line(" default:") fct.line(' throw new IllegalArgumentException("type: " + type);') fct.line(" }") fct.line(" }") fct.line("}"); fct.write() dlg = Output(out_dir, out_pkg, "Delegate") dlg.line("public abstract class Delegate {") for s in structs: dlg.line(" public void %s(C context, %s struct) {}" % (dromedary(s.name), s.name)) dlg.line("}") dlg.write() inv = Output(out_dir, out_pkg, "Invoker") inv.line("public abstract class Invoker {") inv.line() inv.line(" protected abstract void invoke(Method method);") inv.line(" protected abstract Future invoke(Method method, Class resultClass);") inv.line() for s in structs: if s.base != "Method": continue dname = dromedary(s.name) result = s.result() if result: result_type = "Future<%s>" % result else: result_type = "void" inv.line(" public %s %s(%s) {" % (result_type, dname, s.parameters())) if result: inv.line(" return invoke(new %s(%s), %s.class);" % (s.name, s.arguments(), result)) else: inv.line(" invoke(new %s(%s));" % (s.name, s.arguments())) inv.line(" }") inv.line("}") inv.write()