text: import re
  from abc import abstractmethod
  
  from ingest.importer.conversion import data_converter
  from ingest.importer.conversion.column_specification import \
      ColumnSpecification, ConversionType
  from ingest.importer.conversion.data_converter import Converter, ListConverter
  from ingest.importer.conversion.exceptions import UnknownMainCategory
  from ingest.importer.conversion.metadata_entity import MetadataEntity
  from ingest.importer.conversion.utils import split_field_chain
  
  _LIST_CONVERTER = ListConverter()
  
  
  class CellConversion(object):
  
      def __init__(self, field, converter: Converter):
          self.field = field
          self.applied_field = self._process_applied_field(field)
          self.converter = converter
  
      @staticmethod
      def _process_applied_field(field):
          pattern = r'(\w*\.){0,1}(?P<insert_field>.*)'
          match = re.match(pattern, field)
          return match.group('insert_field')
  
      @abstractmethod
      def apply(self, metadata: MetadataEntity, cell_data):
          # TODO Implement this method
          pass
  
  
  class DirectCellConversion(CellConversion):
  
      def apply(self, metadata: MetadataEntity, cell_data):
          if cell_data is not None:
              content = self.converter.convert(cell_data)
              metadata.define_content(self.applied_field, content)
  
  
  class ListElementCellConversion(CellConversion):
  
      def __init__(self, field: str, converter: Converter):
          list_converter = ListConverter(base_converter=converter)
          super(ListElementCellConversion, self).__init__(field, list_converter)
  
      def apply(self, metadata: MetadataEntity, cell_data):
          if cell_data is not None:
              parent_path, target_field = split_field_chain(self.applied_field)
              data_list = self.converter.convert(cell_data)
              parent = self._prepare_array(metadata, parent_path, len(data_list))
              for index, data in enumerate(data_list):
                  target_object = parent[index]
                  target_object[target_field] = data
  
      @staticmethod
      def _prepare_array(metadata, path, child_count):
          parent = metadata.get_content(path)
          if parent is None:
              parent = []
              metadata.define_content(path, parent)
          current_count = len(parent)
          missing_child_count = child_count - current_count
          if missing_child_count > 0:
              missing_children = [{} for _ in range(0, missing_child_count)]
              parent.extend(missing_children)
          return parent
  
  
  class FieldOfSingleElementListCellConversion(CellConversion):
  
      def apply(self, metadata: MetadataEntity, cell_data):
          if cell_data is not None:
              parent_path, target_field = split_field_chain(self.applied_field)
              target_object = self._determine_target_object(metadata, parent_path)
              data = self.converter.convert(cell_data)
              target_object[target_field] = data
  
      @staticmethod
      def _determine_target_object(metadata, parent_path):
          parent = metadata.get_content(parent_path)
          if parent is None:
              target_object = {}
              parent = [target_object]
              metadata.define_content(parent_path, parent)
          else:
              target_object = parent[0]
          return target_object
  
  
  class IdentityCellConversion(CellConversion):
  
      def apply(self, metadata: MetadataEntity, cell_data):
          value = self.converter.convert(cell_data)
          metadata.object_id = metadata.object_id or value
          metadata.define_content(self.applied_field, value)
  
  
  class ExternalReferenceCellConversion(CellConversion):
      def apply(self, metadata: MetadataEntity, cell_data):
          value = self.converter.convert(cell_data)
          metadata._is_reference = True
          metadata.object_id = value
  
  
  class LinkedIdentityCellConversion(CellConversion):
  
      def __init__(self, field, main_category):
          super(LinkedIdentityCellConversion, self).__init__(field, _LIST_CONVERTER)
          self.main_category = main_category
  
      def apply(self, metadata: MetadataEntity, cell_data):
          if self.main_category is None:
              raise UnknownMainCategory()
          if cell_data:
              links = self.converter.convert(cell_data)
              metadata.add_links(self.main_category, links)
  
  
  class LinkedExternalReferenceCellConversion(CellConversion):
  
      def __init__(self, field, main_category):
          super(LinkedExternalReferenceCellConversion, self).__init__(field, _LIST_CONVERTER)
          self.main_category = main_category
  
      def apply(self, metadata: MetadataEntity, cell_data):
          if cell_data:
              links = self.converter.convert(cell_data)
              metadata.add_external_links(self.main_category, links)
  
  
  class LinkingDetailCellConversion(CellConversion):
  
      def apply(self, metadata: MetadataEntity, cell_data):
          value = self.converter.convert(cell_data)
          metadata.define_linking_detail(self.applied_field, value)
  
  
  class DoNothing(CellConversion):
  
      def __init__(self):
          super(DoNothing, self).__init__('', data_converter.DEFAULT)
  
      def apply(self, metadata: MetadataEntity, cell_data):
          pass
  
  
  DO_NOTHING = DoNothing()
  
  
  def determine_strategy(column_spec: ColumnSpecification):
      strategy = DO_NOTHING
      if column_spec is not None:
          field_name = column_spec.field_name
          converter = column_spec.determine_converter()
          conversion_type = column_spec.get_conversion_type()
          if ConversionType.MEMBER_FIELD == conversion_type:
              strategy = DirectCellConversion(field_name, converter)
          elif ConversionType.FIELD_OF_LIST_ELEMENT == conversion_type:
              strategy = ListElementCellConversion(field_name, converter)
          elif ConversionType.LINKING_DETAIL == conversion_type:
              strategy = LinkingDetailCellConversion(field_name, converter)
          elif ConversionType.IDENTITY == conversion_type:
              strategy = IdentityCellConversion(field_name, converter)
          elif ConversionType.LINKED_IDENTITY == conversion_type:
              strategy = LinkedIdentityCellConversion(field_name, column_spec.domain_type)
          elif ConversionType.LINKED_EXTERNAL_REFERENCE == conversion_type:
              strategy = LinkedExternalReferenceCellConversion(field_name, column_spec.domain_type)
          elif ConversionType.EXTERNAL_REFERENCE == conversion_type:
              strategy = ExternalReferenceCellConversion(field_name, converter)
      return strategy
  