Skip to content
Snippets Groups Projects
switch.py 4.69 KiB
Newer Older
##############################################################################
#
#    Converter Odoo module
#    Copyright © 2020 XCG Consulting <https://xcg-consulting.fr>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from collections.abc import Mapping
from typing import Any, Callable, Optional
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from odoo import api, models
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from .base import ContextBuilder, Converter, Skip, SkipType
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from .validate import VALIDATION_SKIP, Validator
Florent Aide's avatar
Florent Aide committed


class Switch(Converter):
    """A converter to handle switch cases.
    A list of converters are provided with a function. The first function to
    match is used, any function that is None will be used.
    The function argument is the model instance.

    Example usage:

    .. code-block:: python

        AURION_REFERENTIAL: Switch(
            [
              (
                  lambda e: e.is_xxx,
                  lambda p: "wave_code" in p,
                  Model("__wave__", {}),
              ),
              (None, None, Model("__event__", {})),
            ]
        )
Florent Aide's avatar
Florent Aide committed
    def __init__(
        self,
                Callable[[models.Model], bool],
                Callable[[Any], bool],
                Converter,
            ]
        ],
        validator: Optional[Validator] = None,
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        validation: str = VALIDATION_SKIP,
Florent Aide's avatar
Florent Aide committed
        context: Optional[ContextBuilder] = None,
    ):
        """
        :param converters: is a 3 tuple composed of:
        out condition, in condition, and chosen converter
        :param validator:
        :param context:
        """
Florent Aide's avatar
Florent Aide committed
        super()
        self._converters = converters
        self.context = context
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        self.validator = validator
        self.validation = validation
Florent Aide's avatar
Florent Aide committed

    def odoo_to_message(
        self, instance: models.Model, ctx: Optional[Mapping] = None
    ) -> Any:
        for out_cond, _in_cond, converter in self._converters:
            if out_cond is None or out_cond(instance):
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                if isinstance(converter, SkipType):
                    return converter
                else:
                    return converter.odoo_to_message(instance, ctx)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        return Skip
    def message_to_odoo(
        self,
        odoo_env: api.Environment,
        phase: str,
        message_value: Any,
        instance: models.Model,
        value_present: bool = True,
        for _out_cond, in_cond, converter in self._converters:
            if in_cond is None or in_cond(message_value):
                return converter.message_to_odoo(
                    odoo_env,
                    phase,
                    message_value,
                    instance,
                    value_present=value_present,
                )

        return Skip

    def is_instance_getter(self) -> bool:
        for _out_cond, _in_cond, converter in self._converters:
            if converter.is_instance_getter():
                return True

        return False

    def get_instance(self, odoo_env, message_data):
        for _out_cond, in_cond, converter in self._converters:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
            if converter.is_instance_getter() and (
                in_cond is None or in_cond(message_data)
            ):
                return converter.get_instance(odoo_env, message_data)

Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    @Converter.validator.setter
    def validator(self, value: Optional[Validator]) -> None:
        # also set validator on any converters in our switch, in case they care
        Converter.validator.fset(self, value)
        for _out_cond, _in_cond, converter in self._converters:
            converter.validator = value
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    @Converter.validation.setter
    def validation(self, value: str) -> None:
        # also set validation on any converters in our switch
        Converter.validation.fset(self, value)
        for _out_cond, _in_cond, converter in self._converters:
            converter.validation = value
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        for _out_cond, _in_cond, converter in self._converters:
            types.update(converter.get__type__())
        return types