def minus(ctx, xs, ys): if len(xs) == 1 and len(ys) == 1: x = util.get_data(xs[0]) y = util.get_data(ys[0]) if util.is_number(x) and util.is_number(y): return x - y if isinstance(x, nodes.FP_TimeBase) and isinstance( y, nodes.FP_Quantity): return x.plus(nodes.FP_Quantity(-y.value, y.unit)) raise Exception("Cannot " + str(xs) + " - " + str(ys))
def ensure_number_singleton(x): data = util.get_data(x) if not util.is_number(data): if not isinstance(data, list) or len(data) != 1: raise Exception("Expected list with number, but got " + str(data)) value = util.get_data(data[0]) if not util.is_number(value): raise Exception("Expected number, but got " + str(x)) return value return data
def typecheck(a, b): """ Checks that the types of a and b are suitable for comparison in an inequality expression. It is assumed that a check has already been made that there is at least one value in a and b. Parameters: a (list) - the left side of the inequality expression (which should be an array of one value) b (list) - the right side of the inequality expression (which should be an array of one value) returns the singleton values of the arrays a, and b. If one was an FP_Type and the other was convertible, the coverted value will be retureed """ rtn = None check_length(a) check_length(b) a = util.get_data(a[0]) b = util.get_data(b[0]) lClass = a.__class__ rClass = b.__class__ areNumbers = util.is_number(a) and util.is_number(b) if lClass != rClass and not areNumbers: d = None # TODO refactor if lClass == str and (rClass == nodes.FP_DateTime or rClass == nodes.FP_Time): d = nodes.FP_DateTime(a) or nodes.FP_Time(a) if d is not None: rtn = [d, b] elif rClass == str and (lClass == nodes.FP_DateTime or lClass == nodes.FP_Time): d = nodes.FP_DateTime(b) or nodes.FP_Time(b) if d is not None: rtn = [a, d] if rtn is None: raise Exception('Type of "' + str(a) + '" (' + lClass.__name__ + ') did not match type of "' + str(b) + '" (' + rClass.__name__ + "). InequalityExpression") if rtn is not None: return rtn return [a, b]
def func(acc, res): data = util.get_data(res) res = create_node(res) if isinstance(data, list): data = dict((i, data[i]) for i in range(0, len(data))) if isinstance(data, dict): for prop in data.keys(): value = data[prop] childPath = "" if res.path is not None: childPath = res.path + "." + prop if (isinstance(model, dict) and "pathsDefinedElsewhere" in model and childPath in model["pathsDefinedElsewhere"]): childPath = model["pathsDefinedElsewhere"][childPath] if isinstance(value, list): mapped = [create_node(n, childPath) for n in value] acc = acc + mapped else: acc.append(create_node(value, childPath)) return acc
def to_integer(ctx, coll): if len(coll) != 1: return [] value = util.get_data(coll[0]) if value == False: return 0 if value == True: return 1 if util.is_number(value): if int(value) == value: return value return [] if str(value): if re.match(intRegex, value) is not None: return int(value) raise Exception("Could not convert to ineger: " + value) return []
def ensure_string_singleton(x): if len(x) == 1: d = util.get_data(x[0]) if type(d) == str: return d raise Exception("Expected string, but got " + str(d)) raise Exception("Expected string, but got " + str(x))
def not_fn(ctx, x): if len(x) != 1: return [] data = util.get_data(x[0]) if type(data) == bool: return not data return []
def plus(ctx, xs, ys): if len(xs) != 1 or len(ys) != 1: raise Exception("Cannot " + str(xs) + " + " + str(ys)) x = util.get_data(xs[0]) y = util.get_data(ys[0]) """ In the future, this and other functions might need to return ResourceNode to preserve the type information (integer vs decimal, and maybe decimal vs string if decimals are represented as strings), in order to support "as" and "is", but that support is deferred for now. """ if type(x) == str and type(y) == str: return x + y if util.is_number(x) and util.is_number(y): return x + y if isinstance(x, nodes.FP_TimeBase) and isinstance(y, nodes.FP_Quantity): return x.plus(y)
def visit(node): data = get_data(node) if isinstance(node, list): return [visit(item) for item in data] if isinstance(data, dict) and not isinstance(data, FP_Type): for key, value in data.items(): data[key] = visit(value) return data
def to_date_time(ctx, coll): ln = len(coll) rtn = [] if ln > 1: raise Exception("to_date_time called for a collection of length " + ln) if ln == 1: value = util.get_data(coll[0]) dateTimeObject = nodes.FP_DateTime(value) if dateTimeObject: rtn[0] = dateTimeObject return rtn
def to_decimal(ctx, coll): if len(coll) != 1: return [] value = util.get_data(coll[0]) if value == False: return 0 if value == True: return 1.0 if util.is_number(value): return value if type(value) == str: if re.match(numRegex, value) is not None: return float(value) raise Exception("Could not convert to decimal: " + value) return []
def check_string_param(val): data = util.get_data(val) if not isinstance(data, str): raise Exception("Expected string, got: " + json.dumps(data)) return data
def to_string(ctx, coll): if len(coll) != 1: return [] value = util.get_data(coll[0]) return str(value)
def check_number_param(val): data = util.get_data(val) if not isinstance(data, numbers.Number): raise Exception("Expected number, got: " + json.dumps(data)) return data
def check_boolean_param(val): data = util.get_data(val) if data == True or data == False: return data raise Exception("Expected boolean, got: " + json.dumps(data))
def extract_boolean_value(data): value = util.get_data(data) if type(value) != bool: raise Exception("Found type '" + type(data) + "' but was expecting bool") return value
def of_type_fn(ctx, coll, tp): return list( filter(lambda x: check_fhir_type(ctx, util.get_data(x), tp), coll))
def check_integer_param(val): data = util.get_data(val) if int(data) != data: raise Exception("Expected integer, got: " + json.dumps(data)) return data