示例#1
0
    def copy_needed(self, traits: 'ResolvedTraitSet', res_guide: 'CdmAttributeResolutionGuidanceDefinition',
                    actions: List['AttributeResolutionApplier']) -> bool:
        if not actions:
            return False

        # For every attribute in the set, detect if a merge of traits will alter the traits. If so, need to copy the
        # attribute set to avoid overwrite.
        for res_att in self._set:
            for trait_action in actions:
                ctx = ApplierContext()
                ctx.res_opt = traits.res_opt
                ctx.res_att_source = res_att
                ctx.res_guide = res_guide

                if trait_action._will_attribute_modify(ctx):
                    return True

        return False
示例#2
0
    def remove_requested_atts(
            self, marker: Tuple[int, int]) -> 'ResolvedAttributeSet':
        # The marker tracks the track the deletes 'under' a certain index.
        (count_index, mark_index) = marker

        # For every attribute in the set, run any attribute removers on the traits they have.
        applied_att_set = None  # type: ResolvedAttributeSet
        for i_att, res_att in enumerate(self._set):
            # Possible for another set to be in this set.
            if isinstance(res_att.target, ResolvedAttributeSet):
                sub_set = cast('ResolvedAttributeSet', res_att.target)
                # Go around again on this same function and get rid of things from this group.
                marker = (count_index, mark_index)
                new_sub_set = sub_set.remove_requested_atts(marker)
                (count_index, mark_index) = marker
                # Replace the set with the new one that came back.
                res_att.target = new_sub_set
                # If everything went away, then remove this group.
                if not new_sub_set or not new_sub_set._set:
                    res_att = None
                else:
                    # Don't count this as an attribute (later).
                    count_index -= 1
            else:
                # This is a good time to make the resolved names final.
                res_att.previous_resolved_name = res_att.resolved_name
                if res_att.arc and res_att.arc.applier_caps and res_att.arc.applier_caps.can_remove:
                    for apl in res_att.arc.actions_remove:
                        # This should look like the applier context when the att was created.
                        ctx = ApplierContext()
                        ctx.res_opt = res_att.arc.res_opt
                        ctx.res_att_source = res_att
                        ctx.res_guide = res_att.arc.res_guide

                        if apl._will_remove(ctx):
                            res_att = None
                            break

            if res_att:
                # Attribute remains. Are we building a new set?
                if applied_att_set:
                    applied_att_set.merge(res_att)
                count_index += 1
            else:
                # Remove the attribute. If this is the first removed attribute, then make a copy of the set now. After
                # this point, the rest of the loop logic keeps the copy going as needed.
                if not applied_att_set:
                    applied_att_set = ResolvedAttributeSet()
                    for i_copy in range(i_att):
                        applied_att_set.merge(self._set[i_copy])

                # Track deletes under the mark (move the mark up)
                if count_index < mark_index:
                    mark_index -= 1

        marker = (count_index, mark_index)

        # Now we are that (or a copy).
        ras_result = self
        if applied_att_set and applied_att_set.size != ras_result.size:
            ras_result = applied_att_set
            ras_result.base_trait_to_attributes = None
            ras_result.attribute_context = self.attribute_context

        return ras_result
示例#3
0
    def apply(
            self, traits: 'ResolvedTraitSet', res_opt: 'ResolveOptions',
            res_guide: 'CdmAttributeResolutionGuidanceDefinition',
            actions: List['AttributeResolutionApplier']
    ) -> 'ResolvedAttributeSet':
        from cdm.objectmodel import CdmAttributeContext

        if not traits and not actions:
            # nothing can change.
            return self

        # for every attribute in the set run any attribute appliers.
        applied_att_set = ResolvedAttributeSet()
        applied_att_set.attribute_context = self.attribute_context

        # check to see if we need to make a copy of the attributes
        # do this when building an attribute context and when we will modify the attributes (beyond traits)
        # see if any of the appliers want to modify
        making_copy = False
        if self._set and applied_att_set.attribute_context and actions:
            res_att_test = self._set[0]
            for trait_action in actions:
                ctx = ApplierContext(res_opt=res_opt,
                                     res_att_source=res_att_test,
                                     res_guide=res_guide)
                if trait_action._will_attribute_modify(ctx):
                    making_copy = True
                    break

        if making_copy:
            # fake up a generation round for these copies that are about to happen
            acp = AttributeContextParameters(
                under=applied_att_set.attribute_context,
                type=CdmAttributeContextType.GENERATED_SET,
                name='_generatedAttributeSet')
            applied_att_set.attribute_context = CdmAttributeContext._create_child_under(
                traits.res_opt, acp)
            acp = AttributeContextParameters(
                under=applied_att_set.attribute_context,
                type=CdmAttributeContextType.GENERATED_ROUND,
                name='_generatedAttributeRound0')

            applied_att_set.attribute_context = CdmAttributeContext._create_child_under(
                traits.res_opt, acp)

        for res_att in self._set:
            att_ctx_to_merge = res_att.att_ctx  # start with the current context for the resolved att, if a copy happens this will change

            if isinstance(res_att.target, ResolvedAttributeSet):
                sub_set = cast('ResolvedAttributeSet', res_att.target)

                if making_copy:
                    res_att = res_att.copy()
                    # making a copy of a subset (att group) also bring along the context tree for that whole group
                    att_ctx_to_merge = res_att.att_ctx

                # the set contains another set. Process those.
                res_att.target = sub_set.apply(traits, res_opt, res_guide,
                                               actions)
            else:
                rts_merge = res_att.resolved_traits.merge_set(traits)
                res_att.resolved_traits = rts_merge

                if actions:
                    for trait_action in actions:
                        ctx = ApplierContext()
                        ctx.res_opt = traits.res_opt
                        ctx.res_att_source = res_att
                        ctx.res_guide = res_guide

                        if trait_action._will_attribute_modify(ctx):
                            # make a context for this new copy
                            if making_copy:
                                acp = AttributeContextParameters(
                                    under=applied_att_set.attribute_context,
                                    type=CdmAttributeContextType.
                                    ATTRIBUTE_DEFINITION,
                                    name=res_att.resolved_name,
                                    regarding=res_att.target)
                                ctx.att_ctx = CdmAttributeContext._create_child_under(
                                    traits.res_opt, acp)
                                att_ctx_to_merge = ctx.att_ctx  # type: CdmAttributeContext

                            # make a copy of the resolved att
                            if making_copy:
                                res_att = res_att.copy()
                                att_ctx_to_merge._add_lineage(res_att.att_ctx)
                                res_att.att_ctx = att_ctx_to_merge

                            ctx.res_att_source = res_att

                            # modify it
                            trait_action._do_attribute_modify(ctx)

            applied_att_set.merge(res_att)

        applied_att_set.attribute_context = self.attribute_context

        return applied_att_set