def compileNullTest(edge): """ RETURN A MVEL EXPRESSION THAT WILL EVALUATE TO true FOR OUT-OF-BOUNDS """ if edge.domain.type not in domains.ALGEBRAIC: Log.error("can only translate time and duration domains") # IS THERE A LIMIT ON THE DOMAIN? value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" if not edge.domain.max: if not edge.domain.min: return False bot = value2MVEL(edge.domain.min) nullTest = "" + value + "<" + bot elif not edge.domain.min: top = value2MVEL(edge.domain.max) nullTest = "" + value + ">=" + top else: top = value2MVEL(edge.domain.max) bot = value2MVEL(edge.domain.min) nullTest = "(" + value + "<" + bot + ") or (" + value + ">=" + top + ")" return nullTest
def compileTime2Term(edge): """ RETURN MVEL CODE THAT MAPS TIME AND DURATION DOMAINS DOWN TO AN INTEGER AND AND THE JAVASCRIPT THAT WILL TURN THAT INTEGER BACK INTO A PARTITION (INCLUDING NULLS) """ if edge.esscript: Log.error("edge script not supported yet") # IS THERE A LIMIT ON THE DOMAIN? numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" nullTest = compileNullTest(edge) ref = coalesce(edge.domain.min, edge.domain.max, datetime(2000, 1, 1)) if edge.domain.interval.month > 0: offset = ref.subtract(ref.floorMonth(), durations.DAY).milli if offset > durations.DAY.milli * 28: offset = ref.subtract(ref.ceilingMonth(), durations.DAY).milli partition2int = "milli2Month(" + value + ", " + value2MVEL( offset) + ")" partition2int = "((" + nullTest + ") ? 0 : " + partition2int + ")" def int2Partition(value): if Math.round(value) == 0: return edge.domain.NULL d = datetime(str(value)[:4:], str(value)[-2:], 1) d = d.addMilli(offset) return edge.domain.getPartByKey(d) else: partition2int = "Math.floor((" + value + "-" + value2MVEL( ref) + ")/" + edge.domain.interval.milli + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey( ref.add(edge.domain.interval.multiply(value))) return Data(toTerm={ "head": "", "body": partition2int }, fromTerm=int2Partition)
def compileDuration2Term(edge): if edge.esscript: Log.error("edge script not supported yet") # IS THERE A LIMIT ON THE DOMAIN? numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" ref = coalesce(edge.domain.min, edge.domain.max, durations.ZERO) nullTest = compileNullTest(edge) ms = edge.domain.interval.milli if edge.domain.interval.month > 0: ms = durations.YEAR.milli / 12 * edge.domain.interval.month partition2int = "Math.floor((" + value + "-" + value2MVEL(ref) + ")/" + ms + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey(ref.add(edge.domain.interval.multiply(value))) return Data(toTerm={"head": "", "body": partition2int}, fromTerm=int2Partition)
def compileDuration2Term(edge): if edge.esscript: Log.error("edge script not supported yet") # IS THERE A LIMIT ON THE DOMAIN? numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" ref = coalesce(edge.domain.min, edge.domain.max, durations.ZERO) nullTest = compileNullTest(edge) ms = edge.domain.interval.milli if edge.domain.interval.month > 0: ms = durations.YEAR.milli / 12 * edge.domain.interval.month partition2int = "Math.floor((" + value + "-" + value2MVEL( ref) + ")/" + ms + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey( ref.add(edge.domain.interval.multiply(value))) return Data(toTerm={ "head": "", "body": partition2int }, fromTerm=int2Partition)
def compileTime2Term(edge): """ RETURN MVEL CODE THAT MAPS TIME AND DURATION DOMAINS DOWN TO AN INTEGER AND AND THE JAVASCRIPT THAT WILL TURN THAT INTEGER BACK INTO A PARTITION (INCLUDING NULLS) """ if edge.esscript: Log.error("edge script not supported yet") # IS THERE A LIMIT ON THE DOMAIN? numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = 'doc["' + value + '"].value' nullTest = compileNullTest(edge) ref = coalesce(edge.domain.min, edge.domain.max, datetime(2000, 1, 1)) if edge.domain.interval.month > 0: offset = ref.subtract(ref.floorMonth(), durations.DAY).milli if offset > durations.DAY.milli * 28: offset = ref.subtract(ref.ceilingMonth(), durations.DAY).milli partition2int = "milli2Month(" + value + ", " + value2MVEL(offset) + ")" partition2int = "((" + nullTest + ") ? 0 : " + partition2int + ")" def int2Partition(value): if Math.round(value) == 0: return edge.domain.NULL d = datetime(str(value)[:4:], str(value)[-2:], 1) d = d.addMilli(offset) return edge.domain.getPartByKey(d) else: partition2int = "Math.floor((" + value + "-" + value2MVEL(ref) + ")/" + edge.domain.interval.milli + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey(ref.add(edge.domain.interval.multiply(value))) return Dict(toTerm={"head": "", "body": partition2int}, fromTerm=int2Partition)
def compileNumeric2Term(edge): if edge.script: Log.error("edge script not supported yet") if edge.domain.type != "numeric" and edge.domain.type != "count": Log.error("can only translate numeric domains") numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" if not edge.domain.max: if not edge.domain.min: ref = 0 partition2int = "Math.floor(" + value + ")/" + value2MVEL( edge.domain.interval) + ")" nullTest = "false" else: ref = value2MVEL(edge.domain.min) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL( edge.domain.interval) + ")" nullTest = "" + value + "<" + ref elif not edge.domain.min: ref = value2MVEL(edge.domain.max) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL( edge.domain.interval) + ")" nullTest = "" + value + ">=" + ref else: top = value2MVEL(edge.domain.max) ref = value2MVEL(edge.domain.min) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL( edge.domain.interval) + ")" nullTest = "(" + value + "<" + ref + ") or (" + value + ">=" + top + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" offset = convert.value2int(ref) def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey((value * edge.domain.interval) + offset) return Data(toTerm={ "head": "", "body": partition2int }, fromTerm=int2Partition)
def compileNumeric2Term(edge): if edge.script: Log.error("edge script not supported yet") if edge.domain.type != "numeric" and edge.domain.type != "count": Log.error("can only translate numeric domains") numPartitions = len(edge.domain.partitions) value = edge.value if isKeyword(value): value = "doc[\"" + value + "\"].value" if not edge.domain.max: if not edge.domain.min: ref = 0 partition2int = "Math.floor(" + value + ")/" + value2MVEL(edge.domain.interval) + ")" nullTest = "false" else: ref = value2MVEL(edge.domain.min) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL(edge.domain.interval) + ")" nullTest = "" + value + "<" + ref elif not edge.domain.min: ref = value2MVEL(edge.domain.max) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL(edge.domain.interval) + ")" nullTest = "" + value + ">=" + ref else: top = value2MVEL(edge.domain.max) ref = value2MVEL(edge.domain.min) partition2int = "Math.floor((" + value + "-" + ref + ")/" + value2MVEL(edge.domain.interval) + ")" nullTest = "(" + value + "<" + ref + ") or (" + value + ">=" + top + ")" partition2int = "((" + nullTest + ") ? " + numPartitions + " : " + partition2int + ")" offset = convert.value2int(ref) def int2Partition(value): if Math.round(value) == numPartitions: return edge.domain.NULL return edge.domain.getPartByKey((value * edge.domain.interval) + offset) return Data(toTerm={"head": "", "body": partition2int}, fromTerm=int2Partition)