Пример #1
0
 def get_reference_info(self, strict=True):
     refs = {}
     for key, info in self.raw_pool.items():
         reference = ConstantTemplate(info['value']).get_reference()
         formatted_reference = ['${%s}' % ref for ref in reference]
         ref = [
             c for c in formatted_reference
             if not strict or c in self.raw_pool
         ]
         refs[key] = ref
     return refs
Пример #2
0
    def _resolve(self):
        maps = {}
        for key in self._refs:
            try:
                ref_val = self._refs[key].value
                if issubclass(ref_val.__class__, Variable):
                    ref_val = ref_val.get()
            except exceptions.ReferenceNotExistError:
                continue
            maps[key] = ref_val
        val = ConstantTemplate(self.value).resolve_data(maps)

        self._value = val
Пример #3
0
    def resolve(self):
        if self.pool:
            return

        refs = self.get_reference_info()

        nodes = refs.keys()
        flows = []
        for node in nodes:
            for ref in refs[node]:
                if ref in nodes:
                    flows.append([node, ref])
        graph = Graph(nodes, flows)
        # circle reference check
        trace = graph.get_cycle()
        if trace:
            raise ConstantReferenceException(
                'Exist circle reference between constants: %s' %
                '->'.join(trace))

        # resolve the constants reference
        pool = {}
        temp_pool = copy.deepcopy(self.raw_pool)
        # get those constants which are referenced only(not refer other constants)
        referenced_only = ConstantPool._get_referenced_only(temp_pool)
        while temp_pool:
            for ref in referenced_only:
                value = temp_pool[ref]['value']

                # resolve those constants which reference the 'ref'
                for key, info in temp_pool.iteritems():
                    maps = {deformat_constant_key(ref): value}
                    temp_pool[key]['value'] = ConstantTemplate(
                        info['value']).resolve_data(maps)

                pool[ref] = temp_pool[ref]
                temp_pool.pop(ref)
            referenced_only = ConstantPool._get_referenced_only(temp_pool)

        self.pool = pool
Пример #4
0
    def _determine_next_flow_with_boolrule(self, data):
        """
        根据当前传入的数据判断下一个应该流向的 flow ( 不使用 eval 的版本)
        :param data:
        :return:
        """
        for condition in self.conditions:
            deformatted_data = {deformat_constant_key(key): value for key, value in data.items()}
            try:
                resolved_evaluate = ConstantTemplate(condition.evaluate).resolve_data(deformatted_data)
                result = BoolRule(resolved_evaluate).test(data)
            except Exception as e:
                raise EvaluationException(
                    'evaluate[%s] fail with data[%s] message: %s' % (
                        condition.evaluate,
                        json.dumps(deformatted_data),
                        e.message
                    )
                )
            if result:
                return condition.sequence_flow

        return None
Пример #5
0
def calculate_constants_type(to_calculate, calculated):
    """
    @summary:
    @param to_calculate: 待计算的变量
    @param calculated: 变量类型确定的,直接放入结果
    @return:
    """
    data = copy.deepcopy(calculated)
    for key, info in to_calculate.items():
        ref = ConstantTemplate(info['value']).get_reference()
        if ref:
            constant_type = 'splice'
        elif info.get('type', 'plain') != 'plain':
            constant_type = info['type']
        else:
            constant_type = 'plain'
        data.setdefault(key, {
            'type': constant_type,
            'value': info['value'],
            'is_param': info.get('is_param', False)
        })

    return data
Пример #6
0
    def targets_meet_condition(self, data):

        targets = []

        for condition in self.conditions:
            deformatted_data = {deformat_constant_key(key): value for key, value in data.items()}
            try:
                resolved_evaluate = ConstantTemplate(condition.evaluate).resolve_data(deformatted_data)
                result = BoolRule(resolved_evaluate).test(data)
            except Exception as e:
                raise EvaluationException(
                    'evaluate[%s] fail with data[%s] message: %s' % (
                        condition.evaluate,
                        json.dumps(deformatted_data),
                        e.message
                    )
                )
            if result:
                targets.append(condition.sequence_flow.target)

        if not targets:
            raise ConditionExhaustedException('all conditions of branches are False')

        return targets
Пример #7
0
def format_web_data_to_pipeline(web_pipeline, is_subprocess=False):
    """
    @summary:
    @param web_pipeline:
    @return:
    """
    pipeline_tree = copy.deepcopy(web_pipeline)
    constants = pipeline_tree.pop('constants')
    classification = classify_constants(constants, is_subprocess)
    # 解析隐藏全局变量互引用
    pool_obj = ConstantPool(classification['constant_pool'])
    pre_resolved_constants = pool_obj.pool
    classification['data_inputs'] = calculate_constants_type(
        pre_resolved_constants, classification['data_inputs'])
    classification['data_inputs'] = calculate_constants_type(
        classification['params'], classification['data_inputs'])
    pipeline_tree['data'] = {
        'inputs': classification['data_inputs'],
        'outputs': [key for key in pipeline_tree.pop('outputs')],
    }

    for act_id, act in pipeline_tree['activities'].items():
        if act['type'] == 'ServiceActivity':
            act_data = act['component'].pop('data')
            # for key, info in act_data.items():
            #     info['value'] = pool_obj.resolve_value(info['value'])

            all_inputs = calculate_constants_type(
                act_data, classification['data_inputs'])
            act['component']['inputs'] = {
                key: value
                for key, value in all_inputs.items() if key in act_data
            }
            act['component']['global_outputs'] = classification[
                'acts_outputs'].get(act_id, {})
        elif act['type'] == 'SubProcess':
            parent_params = {}
            act_constants = {}
            for key, info in act['pipeline']['constants'].items():
                act_constants[key] = info
                if info['show_type'] == 'show':
                    references = ConstantTemplate(
                        info['value']).get_reference()
                    for ref_key in references:
                        formatted_key = format_constant_key(ref_key)
                        if formatted_key in classification['data_inputs']:
                            parent_params[formatted_key] = classification[
                                'data_inputs'][formatted_key]
            act['params'] = parent_params
            act['pipeline'] = format_web_data_to_pipeline(act['pipeline'],
                                                          is_subprocess=True)
        else:
            raise exceptions.FlowTypeError(u"Unknown Activity type: %s" %
                                           act['type'])

    for act in pipeline_tree['activities'].values():
        format_node_io_to_list(act, o=False)

    for gateway in pipeline_tree['gateways'].values():
        format_node_io_to_list(gateway, o=False)

    format_node_io_to_list(pipeline_tree['end_event'], o=False)

    return pipeline_tree
Пример #8
0
 def _build_reference(self, context):
     keys = ConstantTemplate(self.value).get_reference()
     refs = {}
     for key in keys:
         refs[key] = OutputRef(format_constant_key(key), context)
     self._refs = refs
Пример #9
0
def classify_constants(constants, is_subprocess):
    # pipeline tree inputs
    data_inputs = {}
    # pipeline act outputs
    acts_outputs = {}
    for key, info in list(constants.items()):
        # 显示的变量可以引用父流程 context,通过 param 传参
        if info["show_type"] == "show":
            info["is_param"] = True
        else:
            info["is_param"] = False

        if info["custom_type"]:
            var_cls = library.VariableLibrary.get_var_class(
                info["custom_type"])

        # 输出参数
        if info["source_type"] == "component_outputs":
            if info["source_info"].values():
                source_key = list(info["source_info"].values())[0][0]
                source_step = list(info["source_info"].keys())[0]
                # 生成 pipeline 层需要的 pipeline input
                data_inputs[key] = {
                    "type": "splice",
                    "source_act": source_step,
                    "source_key": source_key,
                    "value": info["value"],
                    "is_param": info["is_param"],
                }
                # 生成 pipeline 层需要的 acts_output
                acts_outputs.setdefault(source_step,
                                        {}).update({source_key: key})
        # 自定义的Lazy类型变量
        elif info["custom_type"] and var_cls and issubclass(
                var_cls, var.LazyVariable):
            if (var_cls.type == "meta"
                    and hasattr(var_cls, "process_meta_avalue")
                    and callable(var_cls.process_meta_avalue)):
                value = var_cls.process_meta_avalue(info["meta"],
                                                    info["value"])
            else:
                value = info["value"]
            data_inputs[key] = {
                "type": "lazy",
                "source_tag": info["source_tag"],
                "custom_type": info["custom_type"],
                "value": value,
                "is_param": info["is_param"],
            }
        else:
            ref = ConstantTemplate(info["value"]).get_reference()
            constant_type = "splice" if ref else "plain"
            is_param = info["show_type"] == "show" and is_subprocess
            data_inputs[key] = {
                "type": constant_type,
                "value": info["value"],
                "is_param": is_param
            }

    result = {"data_inputs": data_inputs, "acts_outputs": acts_outputs}
    return result