| # |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| # |
| |
| |
| def pascal(offset, *args): |
| parts = [] |
| for a in args: |
| parts.extend(a.split("-")) |
| return "".join([p[0].upper() + p[1:] for p in parts[:offset]] + [p[0].upper() + p[1:] for p in parts[offset:]]) |
| |
| |
| def scream(*args): |
| return "_".join([a.replace("-", "_").upper() for a in args]) |
| |
| def num(x, default=None): |
| if x is not None and x != "": |
| return int(x, 0) |
| else: |
| return default |
| |
| def klass(nd): |
| parent = nd.parent |
| while parent is not None: |
| if hasattr(parent, "name") and parent.name == "class": |
| return parent |
| parent = parent.parent |
| |
| untyped = -1 |
| |
| def code(nd): |
| global untyped |
| cd = num(nd["@code"]) |
| if cd is None: |
| cd = untyped |
| untyped -= 1 |
| return cd |
| |
| cls = klass(nd) |
| if cls: |
| cd |= (num(cls["@code"]) << 8) |
| return cd |
| |
| def root(nd): |
| if nd.parent is None: |
| return nd |
| else: |
| return root(nd.parent) |
| |
| def qname(nd): |
| name = nd["@name"] |
| cls = klass(nd) |
| if cls != None: |
| return "%s.%s" % (cls["@name"], name) |
| else: |
| return name |
| |
| RESOLVED = {} |
| |
| def resolve(node, name): |
| key = (node, name) |
| if RESOLVED.has_key(key): |
| return RESOLVED[key] |
| else: |
| spec = root(node) |
| cls = klass(node) |
| if cls: |
| for nd in cls.query["#tag"]: |
| if nd["@name"] == name: |
| RESOLVED[key] = nd |
| return nd |
| for nd in spec.query["amqp/#tag"] + spec.query["amqp/class/#tag"]: |
| if name == qname(nd): |
| RESOLVED[key] = nd |
| return nd |
| raise Exception("unresolved name: %s" % name) |
| |
| def resolve_type(nd): |
| if hasattr(nd, "_resolved_type"): |
| return nd._resolved_type |
| else: |
| name = nd["@type"] |
| type = resolve(nd, name) |
| if type.name == "domain" and not type["enum"]: |
| type = resolve_type(type) |
| nd._resolved_type = type |
| return type |
| |
| TYPES = { |
| "bit": "bool", |
| "uint8": "short", |
| "uint16": "int", |
| "uint32": "long", |
| "uint64": "long", |
| "datetime": "long", |
| "uuid": "UUID", |
| "sequence-no": "int", |
| "sequence-set": "RangeSet", # XXX |
| "byte-ranges": "RangeSet", # XXX |
| "str8": "String", |
| "str16": "String", |
| "vbin8": "byte[]", |
| "vbin16": "byte[]", |
| "vbin32": "byte[]", |
| "struct32": "Struct", |
| "map": "Dictionary<String,Object>", |
| "array": "List<Object>" |
| } |
| |
| def cname(nd, field="@name"): |
| cls = klass(nd) |
| if cls: |
| if (nd.name in ("struct", "result") and |
| cls["@name"] != "session" and |
| nd[field] != "header"): |
| return pascal(0, nd[field]) |
| else: |
| return pascal(0, cls["@name"], nd[field]) |
| else: |
| return pascal(0, nd[field]) |
| |
| def jtype(nd): |
| if nd.name == "struct" or nd["enum"]: |
| return cname(nd) |
| else: |
| return TYPES[nd["@name"]] |
| |
| REFS = { |
| "bool": "Boolean", |
| "byte": "Byte", |
| "short": "Short", |
| "int": "Integer", |
| "long": "Long", |
| "float": "Float", |
| "double": "Double", |
| "char": "Character" |
| } |
| |
| def jref(jt): |
| return REFS.get(jt, jt) |
| |
| def jclass(jt): |
| idx = jt.find('<') |
| if idx > 0: |
| return jt[:idx] |
| else: |
| return jt |
| |
| DEFAULTS = { |
| "long": 0, |
| "int": 0, |
| "short": 0, |
| "byte": 0, |
| "char": 0, |
| "bool": "false" |
| } |
| |
| class Field: |
| |
| def __init__(self, index, nd): |
| self.index = index |
| self.name = pascal(1, nd["@name"]) |
| self.type_node = resolve_type(nd) |
| if self.type_node.name == "domain": |
| self.prim_type = resolve_type(self.type_node) |
| else: |
| self.prim_type = self.type_node |
| self.variable_width = num(self.prim_type["@variable-width"], 0) |
| self.fixed_width = num(self.prim_type["@fixed-width"], 0) |
| self.empty = self.variable_width == 0 and self.fixed_width == 0 and self.prim_type.name != "struct" |
| tname = cname(self.type_node) |
| if self.type_node.name == "struct": |
| self.read = "(%s) dec.ReadStruct(%s.TYPE)" % (tname, tname) |
| self.write = "enc.WriteStruct(%s.TYPE, check(struct).%s)" % (tname, self.name) |
| self.coder = "Struct" |
| elif self.type_node.name == "domain": |
| self.coder = pascal(0, self.prim_type["@name"]) |
| self.read = "%s.Get(dec.Read%s())" % (tname, self.coder) |
| self.write = "enc.Write%s(check(struct).%s.GetValue())" % (self.coder, self.name) |
| else: |
| self.coder = pascal(0, self.type_node["@name"]) |
| self.read = "dec.Read%s()" % self.coder |
| self.write = "enc.Write%s(check(struct).%s)" % (self.coder, self.name) |
| self.type = jtype(self.type_node) |
| self.default = DEFAULTS.get(self.type, "null") |
| self.has = pascal(1, "Has", self.name) |
| self.get = pascal(1, "Get", self.name) |
| self.set = pascal(1, "Set", self.name) |
| self.clear = pascal(1, "clear", self.name) |
| if self.type == "bool": |
| self.option = scream(nd["@name"]) |
| else: |
| self.option = None |
| |
| def flag_mask(self, pack): |
| flag = pack * 8 - 8 - (self.index/8)*8 + (self.index % 8) |
| return 1 << flag |
| |
| |
| def get_fields(nd): |
| fields = [] |
| index = 0 |
| for f in nd.query["field"]: |
| fields.append(Field(index, f)) |
| index += 1 |
| return fields |
| |
| def get_parameters(type, fields): |
| params = [] |
| options = False |
| for f in fields: |
| if f.option: |
| options = True |
| else: |
| params.append("%s %s" % (f.type, f.name)) |
| if type["segments"]: |
| params.append("Header header") |
| params.append("MemoryStream body") |
| if options or type.name in ("control", "command"): |
| params.append("Option ... options") |
| return params |
| |
| def get_arguments(type, fields): |
| args = [] |
| options = False |
| for f in fields: |
| if f.option: |
| options = True |
| else: |
| args.append(f.name) |
| if type["segments"]: |
| args.append("header") |
| args.append("body") |
| if options or type.name in ("control", "command"): |
| args.append("options") |
| return args |
| |
| def get_options(fields): |
| return [f for f in fields if f.option] |
| |
| def get_dotnetparameters(type, fields): |
| params = [] |
| options = False |
| for f in fields: |
| if f.option: |
| options = True |
| else: |
| params.append("%s %s" % (f.type, f.name)) |
| if type["segments"]: |
| params.append("Header header") |
| params.append("MemoryStream body") |
| if options or type.name in ("control", "command"): |
| params.append("params Option[] options") |
| return params |