"""_____________________________________________________________________

:PROJECT: LARAsuite

*lara_django_samples high_level_interface *

:details: lara_django_samples high_level_interface.
         - generated with 'lara-django-dev generate_high_level_interface lara_django_samples
:authors: mark doerr <mark.doerr@uni-greifswald.de>

.. note:: -
.. todo:: -
________________________________________________________________________
"""

import json
import asyncio
import logging
import grpc
from typing import Union

from google.protobuf.json_format import MessageToDict

import lara_django_base_grpc.v1.lara_django_base_pb2 as lara_django_base_pb2
import lara_django_base_grpc.v1.lara_django_base_pb2_grpc as lara_django_base_pb2_grpc

import lara_django_samples_grpc.v1.lara_django_samples_pb2 as lara_django_samples_pb2
import lara_django_samples_grpc.v1.lara_django_samples_pb2_grpc as lara_django_samples_pb2_grpc

import  lara_django_base_grpc.lara_django_base_data_model as base_dm
import  lara_django_base_grpc.lara_django_base_interface as base_if
from  lara_django_base_grpc.abstract_interface import LARAInterface, GRPCChannelSingleton, import_model_instance_from_file, export_model_instance_to_file, upload_file, download_file, update_file, upload_image, update_image, download_image, id_cache

import  lara_django_samples_grpc.lara_django_samples_data_model as samples_dm

logger = logging.getLogger(__name__)



#_________________  ExtraData  ______________________


class ExtraDataInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.extradata_class_client = (
        #     lara_django_samples_pb2_grpc.ExtraDataclassByIRIControllerStub(channel)
        # )

        self.extradata_client = lara_django_samples_pb2_grpc.ExtraDataControllerStub(channel)
        
        self.update_item_id = "extradata_id"
        self.stub = self.extradata_client

        self.file_upload_chunk = lara_django_samples_pb2.FileUploadChunk


        # self.extradata_full_client = lara_django_samples_pb2_grpc.ExtraDataFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    @upload_file  # needed for file upload
    async def create(self,  extradata:  list[samples_dm.ExtraData] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.ExtraData]]:
        """ create a list of extradata instances,
               returns a list of extradata data model objects or ids_only

        :param extradata: list of extradata data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of extradata data model objects or ids_only
        """
        extradataclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if extradata_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.extradata_class_client.Retrieve(
        #         lara_django_samples_pb2.ExtraDataclassRetrieveRequest(iri=extradata_class_iri)
        #     )
        #     extradataclass_id = res.extradataclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving extradataclass_id: {e}")
        for extradata in extradata:
            if self._default_namespace_id is not None:
                if extradata.namespace == "" or extradata.namespace == "default":
                    extradata.namespace = self._default_namespace_id
            # extradata.extradata_class = extradataclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.extradata_client.Create(lara_django_samples_pb2.ExtraDataRequest(**extradata.model_dump())) for extradata in extradata )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.extradata_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating extradata: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        extradata_id: str = None,
        extradata_name: str = None,
        #extradata_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.ExtraData]:
        """ retrieve a list of extradata instances by extradata_id, extradata_name or filter_dict,
               returns a list of extradata data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and extradata_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  extradata_id is not None:
            try:
                res =  await self.extradata_client.Retrieve(
                    lara_django_samples_pb2.ExtraDataRetrieveRequest(extradata_id=extradata_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.ExtraData(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving extradata_id: {e}")

        if extradata_name is not None:
            filter_list.append({"name": extradata_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if extradata_name_display is not None:
        #     filter_list.append({"name_display": extradata_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.extradata_client.List(
                        lara_django_samples_pb2.ExtraDataListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.ExtraData(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving extradata_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          extradata_name: str = None,
                          extradata_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the extradata_id for a given extradata_name,
               extradata_name_display or iri
        """
        if extradata_name is not None:
            filter_dict = {"name": extradata_name}
        elif extradata_name_display is not None:
            filter_dict = {"name_display": extradata_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.extradata_client.List(
                lara_django_samples_pb2.ExtraDataListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving extradata_name: {e}")
        if len(results) == 1 :
            return results[0].extradata_id
        else:
            raise ValueError(f"Error retrieving extradata_id - no or too many results found.")
    
    @download_file  # needed for file download
    async def get_by_id(self, extradata_id: str = None) -> samples_dm.ExtraData:
        """ retrieve a extradata data model by extradata_id """
        try:
            res = await self.extradata_client.Retrieve(
                lara_django_samples_pb2.ExtraDataRetrieveRequest(extradata_id=extradata_id)
            )
            return samples_dm.ExtraData(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving extradata_id: {e}")
    
    @download_file  # needed for file download
    async def get_by_name(self, extradata_name: str = None,
                                namespace_uri : str = None) -> samples_dm.ExtraData:
        """ retrieve a extradata data model by extradata_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.extradata_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.ExtraDataRetrieveByNameNSRequest(name=extradata_name, namespace_uri=namespace_uri)
            )
            return samples_dm.ExtraData(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving extradata_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all extradatas """
        if filter_dict is None:
            res = await self.extradata_client.List(lara_django_samples_pb2.ExtraDataListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.extradata_client.List(
                lara_django_samples_pb2.ExtraDataListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.extradata_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all extradatas """
        if self.extradata_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.extradata_full_client.List(
                lara_django_samples_pb2.ExtraDataFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.extradata_full_client.List(
                lara_django_samples_pb2.ExtraDataFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    @update_file  # needed for file update
    async def update(self, extradata : samples_dm.ExtraData = None) -> None:
        """ update a extradata model instance """
        try:
            await self.extradata_client.Update(
                lara_django_samples_pb2.ExtraDataRequest(**extradata.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating extradata_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a extradata by extradata_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.extradata_client.Destroy(lara_django_samples_pb2.ExtraDataDestroyRequest(extradata_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting extradata_id: {e}")

#_________________  SampleLayout  ______________________


class SampleLayoutInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.samplelayout_class_client = (
        #     lara_django_samples_pb2_grpc.SampleLayoutclassByIRIControllerStub(channel)
        # )

        self.samplelayout_client = lara_django_samples_pb2_grpc.SampleLayoutControllerStub(channel)
        
        self.update_item_id = "samplelayout_id"
        self.stub = self.samplelayout_client

        self.file_upload_chunk = lara_django_samples_pb2.FileUploadChunk


        # self.samplelayout_full_client = lara_django_samples_pb2_grpc.SampleLayoutFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    @upload_file  # needed for file upload
    async def create(self,  samplelayouts:  list[samples_dm.SampleLayout] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.SampleLayout]]:
        """ create a list of samplelayout instances,
               returns a list of samplelayout data model objects or ids_only

        :param samplelayouts: list of samplelayout data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of samplelayout data model objects or ids_only
        """
        samplelayoutclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if samplelayout_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.samplelayout_class_client.Retrieve(
        #         lara_django_samples_pb2.SampleLayoutclassRetrieveRequest(iri=samplelayout_class_iri)
        #     )
        #     samplelayoutclass_id = res.samplelayoutclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving samplelayoutclass_id: {e}")
        for samplelayout in samplelayouts:
            if self._default_namespace_id is not None:
                if samplelayout.namespace == "" or samplelayout.namespace == "default":
                    samplelayout.namespace = self._default_namespace_id
            # samplelayout.samplelayout_class = samplelayoutclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.samplelayout_client.Create(lara_django_samples_pb2.SampleLayoutRequest(**samplelayout.model_dump())) for samplelayout in samplelayouts )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.samplelayout_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating samplelayout: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        samplelayout_id: str = None,
        samplelayout_name: str = None,
        #samplelayout_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.SampleLayout]:
        """ retrieve a list of samplelayout instances by samplelayout_id, samplelayout_name or filter_dict,
               returns a list of samplelayout data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and samplelayout_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  samplelayout_id is not None:
            try:
                res =  await self.samplelayout_client.Retrieve(
                    lara_django_samples_pb2.SampleLayoutRetrieveRequest(samplelayout_id=samplelayout_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.SampleLayout(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving samplelayout_id: {e}")

        if samplelayout_name is not None:
            filter_list.append({"name": samplelayout_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if samplelayout_name_display is not None:
        #     filter_list.append({"name_display": samplelayout_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.samplelayout_client.List(
                        lara_django_samples_pb2.SampleLayoutListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.SampleLayout(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving samplelayout_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          samplelayout_name: str = None,
                          samplelayout_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the samplelayout_id for a given samplelayout_name,
               samplelayout_name_display or iri
        """
        if samplelayout_name is not None:
            filter_dict = {"name": samplelayout_name}
        elif samplelayout_name_display is not None:
            filter_dict = {"name_display": samplelayout_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.samplelayout_client.List(
                lara_django_samples_pb2.SampleLayoutListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving samplelayout_name: {e}")
        if len(results) == 1 :
            return results[0].samplelayout_id
        else:
            raise ValueError(f"Error retrieving samplelayout_id - no or too many results found.")
    
    @download_file  # needed for file download
    async def get_by_id(self, samplelayout_id: str = None) -> samples_dm.SampleLayout:
        """ retrieve a samplelayout data model by samplelayout_id """
        try:
            res = await self.samplelayout_client.Retrieve(
                lara_django_samples_pb2.SampleLayoutRetrieveRequest(samplelayout_id=samplelayout_id)
            )
            return samples_dm.SampleLayout(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplelayout_id: {e}")
    
    @download_file  # needed for file download
    async def get_by_name(self, samplelayout_name: str = None,
                                namespace_uri : str = None) -> samples_dm.SampleLayout:
        """ retrieve a samplelayout data model by samplelayout_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.samplelayout_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SampleLayoutRetrieveByNameNSRequest(name=samplelayout_name, namespace_uri=namespace_uri)
            )
            return samples_dm.SampleLayout(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplelayout_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all samplelayouts """
        if filter_dict is None:
            res = await self.samplelayout_client.List(lara_django_samples_pb2.SampleLayoutListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.samplelayout_client.List(
                lara_django_samples_pb2.SampleLayoutListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.samplelayout_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all samplelayouts """
        if self.samplelayout_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.samplelayout_full_client.List(
                lara_django_samples_pb2.SampleLayoutFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.samplelayout_full_client.List(
                lara_django_samples_pb2.SampleLayoutFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    @update_file  # needed for file update
    async def update(self, samplelayout : samples_dm.SampleLayout = None) -> None:
        """ update a samplelayout model instance """
        try:
            await self.samplelayout_client.Update(
                lara_django_samples_pb2.SampleLayoutRequest(**samplelayout.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating samplelayout_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a samplelayout by samplelayout_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.samplelayout_client.Destroy(lara_django_samples_pb2.SampleLayoutDestroyRequest(samplelayout_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting samplelayout_id: {e}")

#_________________  SampleClass  ______________________


class SampleClassInterface:
    def __init__(self, channel: grpc.Channel = None) -> None:
        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.sampleclass_client = lara_django_samples_pb2_grpc.SampleClassControllerStub(channel)
        
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  sampleclasses:  list[samples_dm.SampleClass] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.SampleClass]]:
        try:
            create_coroutines = ( self.sampleclass_client.Create(lara_django_samples_pb2.SampleClassRequest(**sampleclass.model_dump())) for sampleclass in sampleclasses )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.sampleclass_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating sampleclass: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        sampleclass_id: str = None,
        sampleclass_name: str = None,
        #sampleclass_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.SampleClass]:
        """ retrieve a list of sampleclass instances by sampleclass_id, sampleclass_name or filter_dict,
               returns a list of sampleclass data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        filter_list = []
        results_list = []
        if  sampleclass_id is not None:
            try:
                res =  await self.sampleclass_client.Retrieve(
                    lara_django_samples_pb2.SampleClassRetrieveRequest(sampleclass_id=sampleclass_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.SampleClass(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving sampleclass_id: {e}")

        if sampleclass_name is not None:
            filter_list.append({"name": sampleclass_name})
        # if sampleclass_name_display is not None:
        #     filter_list.append({"name_display": sampleclass_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.sampleclass_client.List(
                        lara_django_samples_pb2.SampleClassListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.SampleClass(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving sampleclass_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          sampleclass_name: str = None,
                          sampleclass_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the sampleclass_id for a given sampleclass_name,
               sampleclass_name_display or iri
        """
        if sampleclass_name is not None:
            filter_dict = {"name": sampleclass_name}
        elif sampleclass_name_display is not None:
            filter_dict = {"name_display": sampleclass_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.sampleclass_client.List(
                lara_django_samples_pb2.SampleClassListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving sampleclass_name: {e}")
        if len(results) == 1 :
            return results[0].sampleclass_id
        else:
            raise ValueError(f"Error retrieving sampleclass_id - no or too many results found.")
    
    async def get_by_id(self, sampleclass_id: str = None) -> samples_dm.SampleClass:
        """ retrieve a sampleclass data model by sampleclass_id """
        try:
            res = await self.sampleclass_client.Retrieve(
                lara_django_samples_pb2.SampleClassRetrieveRequest(sampleclass_id=sampleclass_id)
            )
            return samples_dm.SampleClass(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sampleclass_id: {e}")
    
    async def get_by_name(self, sampleclass_name: str = None) -> samples_dm.SampleClass:
        """ retrieve a sampleclass data model by sampleclass_name """
        try:
            res = await self.sampleclass_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SampleClassRetrieveByNameNSRequest(name=sampleclass_name, namespace_uri="")
            )
            return samples_dm.SampleClass(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sampleclass_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all sampleclasss """
        if filter_dict is None:
            res = await self.sampleclass_client.List(lara_django_samples_pb2.SampleClassListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.sampleclass_client.List(
                lara_django_samples_pb2.SampleClassListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.sampleclass_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all sampleclasss """
        if self.sampleclass_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.sampleclass_full_client.List(
                lara_django_samples_pb2.SampleClassFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.sampleclass_full_client.List(
                lara_django_samples_pb2.SampleClassFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, sampleclass : samples_dm.SampleClass = None) -> None:
        """ update a sampleclass model instance """
        try:
            await self.sampleclass_client.Update(
                lara_django_samples_pb2.SampleClassRequest(**sampleclass.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating sampleclass_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a sampleclass by sampleclass_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.sampleclass_client.Destroy(lara_django_samples_pb2.SampleClassDestroyRequest(sampleclass_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting sampleclass_id: {e}")

#_________________  Sample  ______________________


class SampleInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.sample_class_client = (
        #     lara_django_samples_pb2_grpc.SampleclassByIRIControllerStub(channel)
        # )

        self.sample_client = lara_django_samples_pb2_grpc.SampleControllerStub(channel)
        

        # self.sample_full_client = lara_django_samples_pb2_grpc.SampleFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  samples:  list[samples_dm.Sample] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.Sample]]:
        """ create a list of sample instances,
               returns a list of sample data model objects or ids_only

        :param samples: list of sample data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of sample data model objects or ids_only
        """
        sampleclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if sample_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.sample_class_client.Retrieve(
        #         lara_django_samples_pb2.SampleclassRetrieveRequest(iri=sample_class_iri)
        #     )
        #     sampleclass_id = res.sampleclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving sampleclass_id: {e}")
        for sample in samples:
            if self._default_namespace_id is not None:
                if sample.namespace == "" or sample.namespace == "default":
                    sample.namespace = self._default_namespace_id
            # sample.sample_class = sampleclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.sample_client.Create(lara_django_samples_pb2.SampleRequest(**sample.model_dump())) for sample in samples )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.sample_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating sample: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        sample_id: str = None,
        sample_name: str = None,
        #sample_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.Sample]:
        """ retrieve a list of sample instances by sample_id, sample_name or filter_dict,
               returns a list of sample data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and sample_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  sample_id is not None:
            try:
                res =  await self.sample_client.Retrieve(
                    lara_django_samples_pb2.SampleRetrieveRequest(sample_id=sample_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.Sample(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving sample_id: {e}")

        if sample_name is not None:
            filter_list.append({"name": sample_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if sample_name_display is not None:
        #     filter_list.append({"name_display": sample_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.sample_client.List(
                        lara_django_samples_pb2.SampleListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.Sample(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving sample_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          sample_name: str = None,
                          sample_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the sample_id for a given sample_name,
               sample_name_display or iri
        """
        if sample_name is not None:
            filter_dict = {"name": sample_name}
        elif sample_name_display is not None:
            filter_dict = {"name_display": sample_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.sample_client.List(
                lara_django_samples_pb2.SampleListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving sample_name: {e}")
        if len(results) == 1 :
            return results[0].sample_id
        else:
            raise ValueError(f"Error retrieving sample_id - no or too many results found.")
    
    async def get_by_id(self, sample_id: str = None) -> samples_dm.Sample:
        """ retrieve a sample data model by sample_id """
        try:
            res = await self.sample_client.Retrieve(
                lara_django_samples_pb2.SampleRetrieveRequest(sample_id=sample_id)
            )
            return samples_dm.Sample(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sample_id: {e}")
    
    async def get_by_name(self, sample_name: str = None,
                                namespace_uri : str = None) -> samples_dm.Sample:
        """ retrieve a sample data model by sample_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.sample_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SampleRetrieveByNameNSRequest(name=sample_name, namespace_uri=namespace_uri)
            )
            return samples_dm.Sample(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sample_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all samples """
        if filter_dict is None:
            res = await self.sample_client.List(lara_django_samples_pb2.SampleListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.sample_client.List(
                lara_django_samples_pb2.SampleListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.sample_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all samples """
        if self.sample_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.sample_full_client.List(
                lara_django_samples_pb2.SampleFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.sample_full_client.List(
                lara_django_samples_pb2.SampleFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, sample : samples_dm.Sample = None) -> None:
        """ update a sample model instance """
        try:
            await self.sample_client.Update(
                lara_django_samples_pb2.SampleRequest(**sample.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating sample_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a sample by sample_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.sample_client.Destroy(lara_django_samples_pb2.SampleDestroyRequest(sample_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting sample_id: {e}")

#_________________  SamplesSubset  ______________________


class SamplesSubsetInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.samplessubset_class_client = (
        #     lara_django_samples_pb2_grpc.SamplesSubsetclassByIRIControllerStub(channel)
        # )

        self.samplessubset_client = lara_django_samples_pb2_grpc.SamplesSubsetControllerStub(channel)
        

        # self.samplessubset_full_client = lara_django_samples_pb2_grpc.SamplesSubsetFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  samplessubsets:  list[samples_dm.SamplesSubset] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.SamplesSubset]]:
        """ create a list of samplessubset instances,
               returns a list of samplessubset data model objects or ids_only

        :param samplessubsets: list of samplessubset data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of samplessubset data model objects or ids_only
        """
        samplessubsetclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if samplessubset_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.samplessubset_class_client.Retrieve(
        #         lara_django_samples_pb2.SamplesSubsetclassRetrieveRequest(iri=samplessubset_class_iri)
        #     )
        #     samplessubsetclass_id = res.samplessubsetclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving samplessubsetclass_id: {e}")
        for samplessubset in samplessubsets:
            if self._default_namespace_id is not None:
                if samplessubset.namespace == "" or samplessubset.namespace == "default":
                    samplessubset.namespace = self._default_namespace_id
            # samplessubset.samplessubset_class = samplessubsetclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.samplessubset_client.Create(lara_django_samples_pb2.SamplesSubsetRequest(**samplessubset.model_dump())) for samplessubset in samplessubsets )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.samplessubset_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating samplessubset: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        samplessubset_id: str = None,
        samplessubset_name: str = None,
        #samplessubset_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.SamplesSubset]:
        """ retrieve a list of samplessubset instances by samplessubset_id, samplessubset_name or filter_dict,
               returns a list of samplessubset data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and samplessubset_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  samplessubset_id is not None:
            try:
                res =  await self.samplessubset_client.Retrieve(
                    lara_django_samples_pb2.SamplesSubsetRetrieveRequest(samplessubset_id=samplessubset_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.SamplesSubset(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving samplessubset_id: {e}")

        if samplessubset_name is not None:
            filter_list.append({"name": samplessubset_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if samplessubset_name_display is not None:
        #     filter_list.append({"name_display": samplessubset_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.samplessubset_client.List(
                        lara_django_samples_pb2.SamplesSubsetListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.SamplesSubset(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving samplessubset_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          samplessubset_name: str = None,
                          samplessubset_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the samplessubset_id for a given samplessubset_name,
               samplessubset_name_display or iri
        """
        if samplessubset_name is not None:
            filter_dict = {"name": samplessubset_name}
        elif samplessubset_name_display is not None:
            filter_dict = {"name_display": samplessubset_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.samplessubset_client.List(
                lara_django_samples_pb2.SamplesSubsetListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving samplessubset_name: {e}")
        if len(results) == 1 :
            return results[0].samplessubset_id
        else:
            raise ValueError(f"Error retrieving samplessubset_id - no or too many results found.")
    
    async def get_by_id(self, samplessubset_id: str = None) -> samples_dm.SamplesSubset:
        """ retrieve a samplessubset data model by samplessubset_id """
        try:
            res = await self.samplessubset_client.Retrieve(
                lara_django_samples_pb2.SamplesSubsetRetrieveRequest(samplessubset_id=samplessubset_id)
            )
            return samples_dm.SamplesSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplessubset_id: {e}")
    
    async def get_by_name(self, samplessubset_name: str = None,
                                namespace_uri : str = None) -> samples_dm.SamplesSubset:
        """ retrieve a samplessubset data model by samplessubset_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.samplessubset_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SamplesSubsetRetrieveByNameNSRequest(name=samplessubset_name, namespace_uri=namespace_uri)
            )
            return samples_dm.SamplesSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplessubset_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all samplessubsets """
        if filter_dict is None:
            res = await self.samplessubset_client.List(lara_django_samples_pb2.SamplesSubsetListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.samplessubset_client.List(
                lara_django_samples_pb2.SamplesSubsetListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.samplessubset_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all samplessubsets """
        if self.samplessubset_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.samplessubset_full_client.List(
                lara_django_samples_pb2.SamplesSubsetFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.samplessubset_full_client.List(
                lara_django_samples_pb2.SamplesSubsetFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, samplessubset : samples_dm.SamplesSubset = None) -> None:
        """ update a samplessubset model instance """
        try:
            await self.samplessubset_client.Update(
                lara_django_samples_pb2.SamplesSubsetRequest(**samplessubset.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating samplessubset_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a samplessubset by samplessubset_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.samplessubset_client.Destroy(lara_django_samples_pb2.SamplesSubsetDestroyRequest(samplessubset_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting samplessubset_id: {e}")

#_________________  OrderedSamplesSamplesSubset  ______________________


class OrderedSamplesSamplesSubsetInterface:
    def __init__(self, channel: grpc.Channel = None) -> None:
        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.orderedsamplessamplessubset_client = lara_django_samples_pb2_grpc.OrderedSamplesSamplesSubsetControllerStub(channel)
        
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  orderedsamplessamplessubsets:  list[samples_dm.OrderedSamplesSamplesSubset] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.OrderedSamplesSamplesSubset]]:
        try:
            create_coroutines = ( self.orderedsamplessamplessubset_client.Create(lara_django_samples_pb2.OrderedSamplesSamplesSubsetRequest(**orderedsamplessamplessubset.model_dump())) for orderedsamplessamplessubset in orderedsamplessamplessubsets )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.orderedsamplessamplessubset_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating orderedsamplessamplessubset: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        orderedsamplessamplessubset_id: str = None,
        orderedsamplessamplessubset_name: str = None,
        #orderedsamplessamplessubset_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.OrderedSamplesSamplesSubset]:
        """ retrieve a list of orderedsamplessamplessubset instances by orderedsamplessamplessubset_id, orderedsamplessamplessubset_name or filter_dict,
               returns a list of orderedsamplessamplessubset data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        filter_list = []
        results_list = []
        if  orderedsamplessamplessubset_id is not None:
            try:
                res =  await self.orderedsamplessamplessubset_client.Retrieve(
                    lara_django_samples_pb2.OrderedSamplesSamplesSubsetRetrieveRequest(orderedsamplessamplessubset_id=orderedsamplessamplessubset_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.OrderedSamplesSamplesSubset(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving orderedsamplessamplessubset_id: {e}")

        if orderedsamplessamplessubset_name is not None:
            filter_list.append({"name": orderedsamplessamplessubset_name})
        # if orderedsamplessamplessubset_name_display is not None:
        #     filter_list.append({"name_display": orderedsamplessamplessubset_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.orderedsamplessamplessubset_client.List(
                        lara_django_samples_pb2.OrderedSamplesSamplesSubsetListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.OrderedSamplesSamplesSubset(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving orderedsamplessamplessubset_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          orderedsamplessamplessubset_name: str = None,
                          orderedsamplessamplessubset_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the orderedsamplessamplessubset_id for a given orderedsamplessamplessubset_name,
               orderedsamplessamplessubset_name_display or iri
        """
        if orderedsamplessamplessubset_name is not None:
            filter_dict = {"name": orderedsamplessamplessubset_name}
        elif orderedsamplessamplessubset_name_display is not None:
            filter_dict = {"name_display": orderedsamplessamplessubset_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.orderedsamplessamplessubset_client.List(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplessamplessubset_name: {e}")
        if len(results) == 1 :
            return results[0].orderedsamplessamplessubset_id
        else:
            raise ValueError(f"Error retrieving orderedsamplessamplessubset_id - no or too many results found.")
    
    async def get_by_id(self, orderedsamplessamplessubset_id: str = None) -> samples_dm.OrderedSamplesSamplesSubset:
        """ retrieve a orderedsamplessamplessubset data model by orderedsamplessamplessubset_id """
        try:
            res = await self.orderedsamplessamplessubset_client.Retrieve(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetRetrieveRequest(orderedsamplessamplessubset_id=orderedsamplessamplessubset_id)
            )
            return samples_dm.OrderedSamplesSamplesSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplessamplessubset_id: {e}")
    
    async def get_by_name(self, orderedsamplessamplessubset_name: str = None) -> samples_dm.OrderedSamplesSamplesSubset:
        """ retrieve a orderedsamplessamplessubset data model by orderedsamplessamplessubset_name """
        try:
            res = await self.orderedsamplessamplessubset_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetRetrieveByNameNSRequest(name=orderedsamplessamplessubset_name, namespace_uri="")
            )
            return samples_dm.OrderedSamplesSamplesSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplessamplessubset_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all orderedsamplessamplessubsets """
        if filter_dict is None:
            res = await self.orderedsamplessamplessubset_client.List(lara_django_samples_pb2.OrderedSamplesSamplesSubsetListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.orderedsamplessamplessubset_client.List(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.orderedsamplessamplessubset_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all orderedsamplessamplessubsets """
        if self.orderedsamplessamplessubset_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.orderedsamplessamplessubset_full_client.List(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.orderedsamplessamplessubset_full_client.List(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, orderedsamplessamplessubset : samples_dm.OrderedSamplesSamplesSubset = None) -> None:
        """ update a orderedsamplessamplessubset model instance """
        try:
            await self.orderedsamplessamplessubset_client.Update(
                lara_django_samples_pb2.OrderedSamplesSamplesSubsetRequest(**orderedsamplessamplessubset.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating orderedsamplessamplessubset_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a orderedsamplessamplessubset by orderedsamplessamplessubset_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.orderedsamplessamplessubset_client.Destroy(lara_django_samples_pb2.OrderedSamplesSamplesSubsetDestroyRequest(orderedsamplessamplessubset_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting orderedsamplessamplessubset_id: {e}")

#_________________  SampleSet  ______________________


class SampleSetInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.sampleset_class_client = (
        #     lara_django_samples_pb2_grpc.SampleSetclassByIRIControllerStub(channel)
        # )

        self.sampleset_client = lara_django_samples_pb2_grpc.SampleSetControllerStub(channel)
        

        # self.sampleset_full_client = lara_django_samples_pb2_grpc.SampleSetFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  samplesets:  list[samples_dm.SampleSet] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.SampleSet]]:
        """ create a list of sampleset instances,
               returns a list of sampleset data model objects or ids_only

        :param samplesets: list of sampleset data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of sampleset data model objects or ids_only
        """
        samplesetclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if sampleset_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.sampleset_class_client.Retrieve(
        #         lara_django_samples_pb2.SampleSetclassRetrieveRequest(iri=sampleset_class_iri)
        #     )
        #     samplesetclass_id = res.samplesetclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving samplesetclass_id: {e}")
        for sampleset in samplesets:
            if self._default_namespace_id is not None:
                if sampleset.namespace == "" or sampleset.namespace == "default":
                    sampleset.namespace = self._default_namespace_id
            # sampleset.sampleset_class = samplesetclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.sampleset_client.Create(lara_django_samples_pb2.SampleSetRequest(**sampleset.model_dump())) for sampleset in samplesets )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.sampleset_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating sampleset: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        sampleset_id: str = None,
        sampleset_name: str = None,
        #sampleset_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.SampleSet]:
        """ retrieve a list of sampleset instances by sampleset_id, sampleset_name or filter_dict,
               returns a list of sampleset data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and sampleset_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  sampleset_id is not None:
            try:
                res =  await self.sampleset_client.Retrieve(
                    lara_django_samples_pb2.SampleSetRetrieveRequest(sampleset_id=sampleset_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.SampleSet(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving sampleset_id: {e}")

        if sampleset_name is not None:
            filter_list.append({"name": sampleset_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if sampleset_name_display is not None:
        #     filter_list.append({"name_display": sampleset_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.sampleset_client.List(
                        lara_django_samples_pb2.SampleSetListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.SampleSet(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving sampleset_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          sampleset_name: str = None,
                          sampleset_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the sampleset_id for a given sampleset_name,
               sampleset_name_display or iri
        """
        if sampleset_name is not None:
            filter_dict = {"name": sampleset_name}
        elif sampleset_name_display is not None:
            filter_dict = {"name_display": sampleset_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.sampleset_client.List(
                lara_django_samples_pb2.SampleSetListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving sampleset_name: {e}")
        if len(results) == 1 :
            return results[0].sampleset_id
        else:
            raise ValueError(f"Error retrieving sampleset_id - no or too many results found.")
    
    async def get_by_id(self, sampleset_id: str = None) -> samples_dm.SampleSet:
        """ retrieve a sampleset data model by sampleset_id """
        try:
            res = await self.sampleset_client.Retrieve(
                lara_django_samples_pb2.SampleSetRetrieveRequest(sampleset_id=sampleset_id)
            )
            return samples_dm.SampleSet(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sampleset_id: {e}")
    
    async def get_by_name(self, sampleset_name: str = None,
                                namespace_uri : str = None) -> samples_dm.SampleSet:
        """ retrieve a sampleset data model by sampleset_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.sampleset_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SampleSetRetrieveByNameNSRequest(name=sampleset_name, namespace_uri=namespace_uri)
            )
            return samples_dm.SampleSet(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving sampleset_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all samplesets """
        if filter_dict is None:
            res = await self.sampleset_client.List(lara_django_samples_pb2.SampleSetListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.sampleset_client.List(
                lara_django_samples_pb2.SampleSetListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.sampleset_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all samplesets """
        if self.sampleset_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.sampleset_full_client.List(
                lara_django_samples_pb2.SampleSetFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.sampleset_full_client.List(
                lara_django_samples_pb2.SampleSetFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, sampleset : samples_dm.SampleSet = None) -> None:
        """ update a sampleset model instance """
        try:
            await self.sampleset_client.Update(
                lara_django_samples_pb2.SampleSetRequest(**sampleset.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating sampleset_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a sampleset by sampleset_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.sampleset_client.Destroy(lara_django_samples_pb2.SampleSetDestroyRequest(sampleset_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting sampleset_id: {e}")

#_________________  SampleSetsSubset  ______________________


class SampleSetsSubsetInterface:
    def __init__(self, channel: grpc.Channel = None, default_namespace_uri : str = None) -> None:
        self._default_namespace_uri = None
        self._default_namespace_id = None

        # if default_namespace_uri is not None:
        #     await self.set_default_namespace_uri(default_namespace_uri)

        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.namespace_if = base_if.NamespaceInterface(channel)

        # self.samplesetssubset_class_client = (
        #     lara_django_samples_pb2_grpc.SampleSetsSubsetclassByIRIControllerStub(channel)
        # )

        self.samplesetssubset_client = lara_django_samples_pb2_grpc.SampleSetsSubsetControllerStub(channel)
        

        # self.samplesetssubset_full_client = lara_django_samples_pb2_grpc.SampleSetsSubsetFullControllerStub(
        #     channel
        # )

    @property
    def default_namespace_uri(self):
        return self._default_namespace_uri
    @property
    def default_namespace_id(self):
        return self._default_namespace_id

    async def set_default_namespace_uri(self, namespace_uri: str = None):
        if namespace_uri is not None:
            self._default_namespace_uri = namespace_uri.strip()
        try:
            self._default_namespace_id = await self.namespace_if.retrieve_id(namespace_uri=namespace_uri)
        except Exception as e:
            logger.error(f"Error retrieving namespace_id: {e}")
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  samplesetssubsets:  list[samples_dm.SampleSetsSubset] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.SampleSetsSubset]]:
        """ create a list of samplesetssubset instances,
               returns a list of samplesetssubset data model objects or ids_only

        :param samplesetssubsets: list of samplesetssubset data model objects
        :param ids_only: return only the ids of the created instances
        :return: list of samplesetssubset data model objects or ids_only
        """
        samplesetssubsetclass_id = None

        # some sample code for retrieving a class IRI and adding namespace and class to the model
        # if samplesetssubset_class_iri is None:
        #     raise ValueError("No sample class IRI is given.")
        # try:
        #     res = await self.samplesetssubset_class_client.Retrieve(
        #         lara_django_samples_pb2.SampleSetsSubsetclassRetrieveRequest(iri=samplesetssubset_class_iri)
        #     )
        #     samplesetssubsetclass_id = res.samplesetssubsetclass_id
        # except Exception as e:
        #     logger.error(f"Error retrieving samplesetssubsetclass_id: {e}")
        for samplesetssubset in samplesetssubsets:
            if self._default_namespace_id is not None:
                if samplesetssubset.namespace == "" or samplesetssubset.namespace == "default":
                    samplesetssubset.namespace = self._default_namespace_id
            # samplesetssubset.samplesetssubset_class = samplesetssubsetclass_id # uncomment if a model class is used

        try:
            create_coroutines = ( self.samplesetssubset_client.Create(lara_django_samples_pb2.SampleSetsSubsetRequest(**samplesetssubset.model_dump())) for samplesetssubset in samplesetssubsets )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.samplesetssubset_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating samplesetssubset: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        namespace_uri: str = None,
        samplesetssubset_id: str = None,
        samplesetssubset_name: str = None,
        #samplesetssubset_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.SampleSetsSubset]:
        """ retrieve a list of samplesetssubset instances by samplesetssubset_id, samplesetssubset_name or filter_dict,
               returns a list of samplesetssubset data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None and samplesetssubset_id is None:
            # TODO: define NoNamespaceURIError
            raise ValueError("No namespace URI is given.")
        filter_list = []
        results_list = []
        if  samplesetssubset_id is not None:
            try:
                res =  await self.samplesetssubset_client.Retrieve(
                    lara_django_samples_pb2.SampleSetsSubsetRetrieveRequest(samplesetssubset_id=samplesetssubset_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.SampleSetsSubset(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving samplesetssubset_id: {e}")

        if samplesetssubset_name is not None:
            filter_list.append({"name": samplesetssubset_name})
        if namespace_uri is not None:
            filter_list.append({"namespace__uri": namespace_uri})
        # if samplesetssubset_name_display is not None:
        #     filter_list.append({"name_display": samplesetssubset_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.samplesetssubset_client.List(
                        lara_django_samples_pb2.SampleSetsSubsetListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.SampleSetsSubset(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving samplesetssubset_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          samplesetssubset_name: str = None,
                          samplesetssubset_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the samplesetssubset_id for a given samplesetssubset_name,
               samplesetssubset_name_display or iri
        """
        if samplesetssubset_name is not None:
            filter_dict = {"name": samplesetssubset_name}
        elif samplesetssubset_name_display is not None:
            filter_dict = {"name_display": samplesetssubset_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.samplesetssubset_client.List(
                lara_django_samples_pb2.SampleSetsSubsetListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving samplesetssubset_name: {e}")
        if len(results) == 1 :
            return results[0].samplesetssubset_id
        else:
            raise ValueError(f"Error retrieving samplesetssubset_id - no or too many results found.")
    
    async def get_by_id(self, samplesetssubset_id: str = None) -> samples_dm.SampleSetsSubset:
        """ retrieve a samplesetssubset data model by samplesetssubset_id """
        try:
            res = await self.samplesetssubset_client.Retrieve(
                lara_django_samples_pb2.SampleSetsSubsetRetrieveRequest(samplesetssubset_id=samplesetssubset_id)
            )
            return samples_dm.SampleSetsSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplesetssubset_id: {e}")
    
    async def get_by_name(self, samplesetssubset_name: str = None,
                                namespace_uri : str = None) -> samples_dm.SampleSetsSubset:
        """ retrieve a samplesetssubset data model by samplesetssubset_name """
        if namespace_uri is None and self._default_namespace_uri is not None:
            namespace_uri = self._default_namespace_uri
        if namespace_uri is None:
            raise ValueError("No namespace URI is given.")
        try:
            res = await self.samplesetssubset_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.SampleSetsSubsetRetrieveByNameNSRequest(name=samplesetssubset_name, namespace_uri=namespace_uri)
            )
            return samples_dm.SampleSetsSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving samplesetssubset_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all samplesetssubsets """
        if filter_dict is None:
            res = await self.samplesetssubset_client.List(lara_django_samples_pb2.SampleSetsSubsetListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.samplesetssubset_client.List(
                lara_django_samples_pb2.SampleSetsSubsetListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.samplesetssubset_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all samplesetssubsets """
        if self.samplesetssubset_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.samplesetssubset_full_client.List(
                lara_django_samples_pb2.SampleSetsSubsetFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.samplesetssubset_full_client.List(
                lara_django_samples_pb2.SampleSetsSubsetFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, samplesetssubset : samples_dm.SampleSetsSubset = None) -> None:
        """ update a samplesetssubset model instance """
        try:
            await self.samplesetssubset_client.Update(
                lara_django_samples_pb2.SampleSetsSubsetRequest(**samplesetssubset.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating samplesetssubset_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a samplesetssubset by samplesetssubset_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.samplesetssubset_client.Destroy(lara_django_samples_pb2.SampleSetsSubsetDestroyRequest(samplesetssubset_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting samplesetssubset_id: {e}")

#_________________  OrderedSamplesetsSamplesetsSubset  ______________________


class OrderedSamplesetsSamplesetsSubsetInterface:
    def __init__(self, channel: grpc.Channel = None) -> None:
        if channel is None:
            cs = GRPCChannelSingleton()
            channel = cs.channel

        self.orderedsamplesetssamplesetssubset_client = lara_django_samples_pb2_grpc.OrderedSamplesetsSamplesetsSubsetControllerStub(channel)
        
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def create(self,  orderedsamplesetssamplesetssubsets:  list[samples_dm.OrderedSamplesetsSamplesetsSubset] = None,  ids_only: bool = False) -> Union[list[str], list[samples_dm.OrderedSamplesetsSamplesetsSubset]]:
        try:
            create_coroutines = ( self.orderedsamplesetssamplesetssubset_client.Create(lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetRequest(**orderedsamplesetssamplesetssubset.model_dump())) for orderedsamplesetssamplesetssubset in orderedsamplesetssamplesetssubsets )
            res = await asyncio.gather(*create_coroutines)
            if ids_only:
                return [item.orderedsamplesetssamplesetssubset_id for item in res]
            else:
                return res

        except Exception as e:
            logger.error(f"Error creating orderedsamplesetssamplesetssubset: {e}")
        
    @export_model_instance_to_file
    async def retrieve(
        self,
        orderedsamplesetssamplesetssubset_id: str = None,
        orderedsamplesetssamplesetssubset_name: str = None,
        #orderedsamplesetssamplesetssubset_name_display: str = None,
        filter_dict: dict = None,
        raw : bool = False
        ) -> list[samples_dm.OrderedSamplesetsSamplesetsSubset]:
        """ retrieve a list of orderedsamplesetssamplesetssubset instances by orderedsamplesetssamplesetssubset_id, orderedsamplesetssamplesetssubset_name or filter_dict,
               returns a list of orderedsamplesetssamplesetssubset data model objects,
               if raw is True, the raw protobuf objects are returned
        """
        filter_list = []
        results_list = []
        if  orderedsamplesetssamplesetssubset_id is not None:
            try:
                res =  await self.orderedsamplesetssamplesetssubset_client.Retrieve(
                    lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetRetrieveRequest(orderedsamplesetssamplesetssubset_id=orderedsamplesetssamplesetssubset_id) )
                if raw:
                    results_list.append(res)
                else:
                    results_list.append( samples_dm.OrderedSamplesetsSamplesetsSubset(**MessageToDict(res, preserving_proto_field_name=True)) )
            except Exception as e:
                logger.error(f"Error retrieving orderedsamplesetssamplesetssubset_id: {e}")

        if orderedsamplesetssamplesetssubset_name is not None:
            filter_list.append({"name": orderedsamplesetssamplesetssubset_name})
        # if orderedsamplesetssamplesetssubset_name_display is not None:
        #     filter_list.append({"name_display": orderedsamplesetssamplesetssubset_name_display})
        if filter_dict is not None:
            filter_list.append(filter_dict)

        for filter_dict in filter_list:
            metadata = (("filters", (json.dumps(filter_dict))),)
            try:
                res = await self.orderedsamplesetssamplesetssubset_client.List(
                        lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetListRequest(), metadata=metadata
                      )
                if raw:
                      results_list += res.results
                else:
                    # a queue could be used here to speed up the retrieval
                    results = res.results
                    results_list += [ samples_dm.OrderedSamplesetsSamplesetsSubset(**MessageToDict(res, preserving_proto_field_name=True)) for res in results ]
            except Exception as e:
                logger.error(f"Error retrieving orderedsamplesetssamplesetssubset_name: {e}")

        return results_list

    #@id_cache
    async def retrieve_id(self,
                          orderedsamplesetssamplesetssubset_name: str = None,
                          orderedsamplesetssamplesetssubset_name_display: str = None,
                          iri: str = None,) -> str:
        """ retrieve the orderedsamplesetssamplesetssubset_id for a given orderedsamplesetssamplesetssubset_name,
               orderedsamplesetssamplesetssubset_name_display or iri
        """
        if orderedsamplesetssamplesetssubset_name is not None:
            filter_dict = {"name": orderedsamplesetssamplesetssubset_name}
        elif orderedsamplesetssamplesetssubset_name_display is not None:
            filter_dict = {"name_display": orderedsamplesetssamplesetssubset_name_display}
        elif iri is not None:
            filter_dict = {"iri": iri}
        metadata = (("filters", (json.dumps(filter_dict))),)
        try:
            res = await self.orderedsamplesetssamplesetssubset_client.List(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetListRequest(), metadata=metadata
            )
            results = res.results
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplesetssamplesetssubset_name: {e}")
        if len(results) == 1 :
            return results[0].orderedsamplesetssamplesetssubset_id
        else:
            raise ValueError(f"Error retrieving orderedsamplesetssamplesetssubset_id - no or too many results found.")
    
    async def get_by_id(self, orderedsamplesetssamplesetssubset_id: str = None) -> samples_dm.OrderedSamplesetsSamplesetsSubset:
        """ retrieve a orderedsamplesetssamplesetssubset data model by orderedsamplesetssamplesetssubset_id """
        try:
            res = await self.orderedsamplesetssamplesetssubset_client.Retrieve(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetRetrieveRequest(orderedsamplesetssamplesetssubset_id=orderedsamplesetssamplesetssubset_id)
            )
            return samples_dm.OrderedSamplesetsSamplesetsSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplesetssamplesetssubset_id: {e}")
    
    async def get_by_name(self, orderedsamplesetssamplesetssubset_name: str = None) -> samples_dm.OrderedSamplesetsSamplesetsSubset:
        """ retrieve a orderedsamplesetssamplesetssubset data model by orderedsamplesetssamplesetssubset_name """
        try:
            res = await self.orderedsamplesetssamplesetssubset_client.RetrieveByNameNamespace(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetRetrieveByNameNSRequest(name=orderedsamplesetssamplesetssubset_name, namespace_uri="")
            )
            return samples_dm.OrderedSamplesetsSamplesetsSubset(**MessageToDict(res, preserving_proto_field_name=True))
        except Exception as e:
            logger.error(f"Error retrieving orderedsamplesetssamplesetssubset_name: {e}")
    
    async def list_items(self, filter_dict: dict = None, ids_only: bool = False) -> list[str]:
        """ list all orderedsamplesetssamplesetssubsets """
        if filter_dict is None:
            res = await self.orderedsamplesetssamplesetssubset_client.List(lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetListRequest())
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            res = await self.orderedsamplesetssamplesetssubset_client.List(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetListRequest(), metadata=metadata
            )
        if res is not None and ids_only:
            return [item.orderedsamplesetssamplesetssubset_id for item in res.results]
        else:
            return res.results

    async def list_full(self, filter_dict: dict = None) -> list:
        """ list all orderedsamplesetssamplesetssubsets """
        if self.orderedsamplesetssamplesetssubset_full_client is None:
            raise ValueError("No full client available.")
        if filter_dict is None:
            return await self.orderedsamplesetssamplesetssubset_full_client.List(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetFullListRequest()
            )
        else:
            metadata = (("filters", (json.dumps(filter_dict))),)
            return await self.orderedsamplesetssamplesetssubset_full_client.List(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetFullListRequest(), metadata=metadata
            )
    
    @import_model_instance_from_file(relation_resolver=lambda x: x)
    async def update(self, orderedsamplesetssamplesetssubset : samples_dm.OrderedSamplesetsSamplesetsSubset = None) -> None:
        """ update a orderedsamplesetssamplesetssubset model instance """
        try:
            await self.orderedsamplesetssamplesetssubset_client.Update(
                lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetRequest(**orderedsamplesetssamplesetssubset.model_dump()
            ))
        except Exception as e:
            logger.error(f"Error updating orderedsamplesetssamplesetssubset_id: {e}")
    
    async def delete(self, id_list: list[str] = None, filter_dict: dict = None) -> None:
        """ delete a orderedsamplesetssamplesetssubset by orderedsamplesetssamplesetssubset_id or filter_dict """
        if filter_dict is not None:
            id_list = await self.list_items(filter_dict=filter_dict, ids_only=True)

        try:
            delete_coroutines = ( self.orderedsamplesetssamplesetssubset_client.Destroy(lara_django_samples_pb2.OrderedSamplesetsSamplesetsSubsetDestroyRequest(orderedsamplesetssamplesetssubset_id=id)) for id in id_list )
            await asyncio.gather(*delete_coroutines)

        except Exception as e:
            logger.error(f"Error deleting orderedsamplesetssamplesetssubset_id: {e}")

