def do_smart_selection_adaption(selection, parent_m):
        """ Reduce and extend transition and data flow element selection if already enclosed by selection

         The smart selection adaptation checks and ignores directly data flows and transitions which are selected
         without selected related origin or targets elements. Additional the linkage (data flows and transitions)
         if those origins and targets are covered by the selected elements is added to the selection.
         Thereby the selection it self is manipulated to provide direct feedback to the user.

        :param selection:
        :param parent_m:
        :return:
        """

        def get_ports_related_to_data_flow(data_flow):
            from_port = data_flow.parent.get_data_port(data_flow.from_state, data_flow.from_key)
            to_port = data_flow.parent.get_data_port(data_flow.to_state, data_flow.to_key)
            return from_port, to_port

        def get_states_related_to_transition(transition):
            if transition.from_state == transition.parent.state_id or transition.from_state is None:
                from_state = transition.parent
            else:
                from_state = transition.parent.states[transition.from_state]
            if transition.to_state == transition.parent.state_id:
                to_state = transition.parent
            else:
                to_state = transition.parent.states[transition.to_state]
            if transition.to_outcome in transition.parent.outcomes:
                to_outcome = transition.parent.outcomes[transition.to_outcome]
            else:
                to_outcome = transition.to_outcome
            return from_state, to_state, to_outcome

        # reduce linkage selection by not fully by selection covered linkage
        possible_states = [state_m.state for state_m in selection.states]
        possible_outcomes = [outcome_m.outcome for outcome_m in selection.outcomes]
        for data_flow_m in selection.data_flows:
            from_port, to_port = get_ports_related_to_data_flow(data_flow_m.data_flow)
            if from_port.parent not in possible_states or to_port not in possible_states:
                selection.remove(data_flow_m)
        for transition_m in selection.transitions:
            from_state, to_state, to_oc = get_states_related_to_transition(transition_m.transition)
            if from_state not in possible_states or (to_state not in possible_states and to_oc not in possible_outcomes):
                selection.remove(transition_m)

        # extend linkage selection by fully by selected element enclosed linkage
        if parent_m and isinstance(parent_m.state, ContainerState):
            state_ids = [state.state_id for state in possible_states]
            port_ids = [sv_m.scoped_variable.data_port_id for sv_m in selection.scoped_variables] + \
                [ip_m.data_port.data_port_id for ip_m in selection.input_data_ports] + \
                [op_m.data_port.data_port_id for op_m in selection.output_data_ports]
            ports = [sv_m.scoped_variable for sv_m in selection.scoped_variables] + \
                [ip_m.data_port for ip_m in selection.input_data_ports] + \
                [op_m.data_port for op_m in selection.output_data_ports]
            related_transitions, related_data_flows = \
                parent_m.state.related_linkage_states_and_scoped_variables(state_ids, port_ids)
            # extend by selected states or a port and a state enclosed data flows
            for data_flow in related_data_flows['enclosed']:
                data_flow_m = parent_m.get_data_flow_m(data_flow.data_flow_id)
                if data_flow_m not in selection.data_flows:
                    selection.add(data_flow_m)
            # extend by selected ports enclosed data flows
            for data_flow_id, data_flow in parent_m.state.data_flows.items():
                from_port, to_port = get_ports_related_to_data_flow(data_flow)
                if from_port in ports and to_port in ports:
                    selection.add(parent_m.get_data_flow_m(data_flow_id))
            # extend by selected states enclosed transitions
            for transition in related_transitions['enclosed']:
                transition_m = parent_m.get_transition_m(transition.transition_id)
                if transition_m not in selection.transitions:
                    selection.add(transition_m)
            # extend by selected state and outcome enclosed transitions
            for transition_id, transition in parent_m.state.transitions.items():
                from_state, to_state, to_oc = get_states_related_to_transition(transition)
                if from_state in possible_states and to_oc in possible_outcomes:
                    selection.add(parent_m.get_transition_m(transition_id))