#!/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) major = spec["amqp/@major"] minor = spec["amqp/@minor"] isfx = "_v%s_%s" % (major, minor) 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": "Range[]" } def camel(offset, *args): parts = [] for a in args: parts.extend(a.split("-")) return "".join(parts[:offset] + [p.capitalize() 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 = {} EXCLUDE = {"access-ticket": True} for d in spec.query["amqp/domain"]: DOMAINS[d["@name"]] = d["@type"] def resolve(type): if DOMAINS.has_key(type) and DOMAINS[type] != type: return resolve(DOMAINS[type]) else: return type OPTIONS = {} class Struct: def __init__(self, type, name): self.type = type self.name = name self.fields = [] def field(self, type, name): self.fields.append((type, name)) def interface(self, out): out.line("public interface %s extends Method {" % self.name) out.line() out.line(" public static final int TYPE = %d;" % self.type) out.line() for type, name in self.fields: out.line(" %s %s();" % (TYPES[type], camel(1, "get", name))) out.line() out.line("}") def impl(self, out): out.line("class %s%s extends AbstractMethod implements %s {" % (self.name, isfx, self.name)) out.line() out.line(" public int getEncodedType() {") out.line(" return TYPE;") out.line(" }") out.line() for type, name in self.fields: out.line(" private final %s %s;" % (TYPES[type], name)) out.line() out.line(" %s%s(Decoder dec) {" % (self.name, isfx)) for type, name in self.fields: out.line(" %s = dec.read%s();" % (name, camel(0, type))) out.line(" }") out.line() out.line(" %s%s(%s) {" % (self.name, isfx, 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(' 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(" }") out.line() for type, name in self.fields: out.line(" public %s %s() {" % (TYPES[type], camel(1, "get", name))) out.line(" return %s;" % name) out.line(" }") out.line() out.line(" public void write(Encoder enc) {") for type, name in self.fields: out.line(" enc.write%s(%s);" % (camel(0, type), name)) 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" % (TYPES[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} opts = Output(out_dir, out_pkg, "Option") opts.line("public enum Option {") structs = [] for m in spec.query["amqp/class/method", lambda m: CLASSES.get(m.parent["@name"], True)]: struct = Struct(int(m.parent["@index"])*256 + int(m["@index"]), camel(0, m.parent["@name"], m["@name"])) 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("}") opts.write() for s in structs: out = Output(out_dir, out_pkg, s.name) s.interface(out) out.write() iout = Output(out_dir, out_pkg, s.name + isfx) s.impl(iout) iout.write() fct = Output(out_dir, out_pkg, "StructFactory") fct.line("public interface StructFactory {") fct.line(" Struct create(int type, Decoder dec);") for s in structs: fct.line() fct.line(" %s new%s(Decoder dec);" % (s.name, s.name)) fct.line(" %s new%s(%s);" % (s.name, s.name, s.parameters())) fct.line("}") fct.write() ifct_name = "StructFactory%s" % isfx ifct = Output(out_dir, out_pkg, ifct_name) ifct.line("class %s implements StructFactory {" % ifct_name) ifct.line(" public Struct create(int type, Decoder dec) {") ifct.line(" switch (type) {") for s in structs: ifct.line(" case %s.TYPE:" % s.name) ifct.line(" return new %s%s(dec);" % (s.name, isfx)) ifct.line(" default:") ifct.line(' throw new IllegalArgumentException("type: " + type);') ifct.line(" }") ifct.line(" }") for s in structs: ifct.line(" public %s new%s(Decoder dec) {" % (s.name, s.name)) ifct.line(" return new %s%s(dec);" % (s.name, isfx)) ifct.line(" }") ifct.line(" public %s new%s(%s) {" % (s.name, s.name, s.parameters())) ifct.line(" return new %s%s(%s);" % (s.name, isfx, s.arguments())) ifct.line(" }") ifct.line("}"); ifct.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 void invoke(Method method, Handler handler);") inv.line(" protected abstract StructFactory getFactory();") inv.line() for s in structs: dname = dromedary(s.name) inv.line(" public void %s(%s) throws QpidException {" % (dname, s.parameters())) inv.line(" invoke(getFactory().new%s(%s));" % (s.name, s.arguments())) inv.line(" }") inv.line("}") inv.write() for pset in ("DeliveryProperties", "ApplicationProperties"): hdrs = Output(out_dir, out_pkg, pset) hdrs.line("public interface %s extends Header {}" % pset) hdrs.write()