mapper.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. from abc import (
  2. ABCMeta,
  3. abstractmethod
  4. )
  5. from typing import Optional
  6. from dataladmetadatamodel.log import logger
  7. from dataladmetadatamodel.mapper.reference import Reference
  8. class Mapper(metaclass=ABCMeta):
  9. """
  10. Mapper are responsible for populating an existing
  11. object of a certain class from a backend. The mapper
  12. will delegate sub-object mapping to the mapper for
  13. the class of the sub-object.
  14. This base class handles default destination
  15. """
  16. def __init__(self,
  17. class_name: str,
  18. default_destination: Optional[str] = None):
  19. self.class_name = class_name
  20. self.destination = default_destination
  21. def map_in(self,
  22. mappable_object: "MappableObject",
  23. realm: str,
  24. reference: Reference) -> None:
  25. # Check for old-style file tree and dataset tree references
  26. if reference.class_name in ("FileTree", "DatasetTree"):
  27. logger.warning(f"Mapper.map_in(): converting reference to class "
  28. f"{reference.class_name} to a reference to class "
  29. f"MTreeNode")
  30. reference.class_name = "MTreeNode"
  31. # TODO: this is not too nice, but required since FileTree and
  32. # DatasetTree are proxies for MTreeNode which just add some
  33. # methods.
  34. mo_class_name = type(mappable_object).__name__
  35. if mo_class_name in ("FileTree", "DatasetTree"):
  36. assert self.class_name == "MTreeNode", \
  37. f"Mappable object class: {mo_class_name} " \
  38. f"can not be mapped in by a mapper for class: {self.class_name}"
  39. else:
  40. assert mo_class_name == self.class_name, \
  41. f"Mappable object class name ({mo_class_name}) " \
  42. f"does not match this mapper's class_name ({self.class_name})"
  43. assert reference.class_name == self.class_name, \
  44. f"Reference class name ({reference.class_name}) " \
  45. f"does not match self.class_name ({self.class_name})"
  46. self.map_in_impl(mappable_object, realm, reference)
  47. def map_out(self,
  48. mappable_object: "MappableObject",
  49. realm: Optional[str] = None,
  50. force_write: bool = False) -> Reference:
  51. if realm is None:
  52. if self.destination is None:
  53. raise Exception(
  54. "'destination' not set and no default destination provided")
  55. realm = self.destination
  56. return self.map_out_impl(mappable_object, realm, force_write)
  57. @abstractmethod
  58. def map_in_impl(self,
  59. mappable_object: "MappableObject",
  60. realm: str,
  61. reference: Reference) -> None:
  62. raise NotImplementedError
  63. @abstractmethod
  64. def map_out_impl(self,
  65. mappable_object: "MappableObject",
  66. realm: str,
  67. force_write: bool) -> Reference:
  68. raise NotImplementedError