Skip to content
Snippets Groups Projects
switch.py 4.79 KiB
Newer Older
##############################################################################
#
#    Converter Odoo module
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
#    Copyright © 2020, 2024 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/>.
#
##############################################################################
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from collections.abc import Callable
Axel Prel's avatar
Axel Prel committed
from typing import Any
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from odoo import api, models  # type: ignore[import-untyped]
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
from .base import Context, ContextBuilder, Converter, NewinstanceType, Skip, SkipType
from .validate import Validation, 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,
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                Callable[[models.BaseModel], bool] | None,
                Callable[[Any], bool],
                Converter,
            ]
        ],
Axel Prel's avatar
Axel Prel committed
        validator: Validator | None = None,
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        validation: str = Validation.SKIP,
Axel Prel's avatar
Axel Prel committed
        context: ContextBuilder | None = None,
Florent Aide's avatar
Florent Aide committed
    ):
        """
        :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
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    def odoo_to_message(self, instance: models.BaseModel, ctx: Context = 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,
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        instance: models.BaseModel,
        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,
                )

Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        return {}
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    @property
    def is_instance_getter(self) -> bool:
        for _out_cond, _in_cond, converter in self._converters:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
            if converter.is_instance_getter:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    def get_instance(
        self, odoo_env: api.Environment, message_data
    ) -> models.BaseModel | NewinstanceType | None:
        for _out_cond, in_cond, converter in self._converters:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
            if converter.is_instance_getter and (
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
                in_cond is None or in_cond(message_data)
            ):
                return converter.get_instance(odoo_env, message_data)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        return super().get_instance(odoo_env, message_data)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    def _set_validator(self, value: Validator | None) -> None:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        # also set validator on any converters in our switch, in case they care
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        super()._set_validator(value)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        for _out_cond, _in_cond, converter in self._converters:
            converter.validator = value
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    def _set_validation(self, value: str) -> None:
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        # also set validation on any converters in our switch
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        super()._set_validation(value)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
        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