from django.db import models
from haystack.signals import RealtimeSignalProcessor
from haystack.exceptions import NotHandled
import logging
import types
from haystack.query import SearchQuerySet
from haystack.utils import get_identifier

logger = logging.getLogger(__name__)


class HydroRealtimeSignalProcessor(RealtimeSignalProcessor):

    """ 
    Customized for the fact that all indexed resources are subclasses of BaseResource. 
    Notes: 
    1. RealtimeSignalProcessor already plumbs in all class updates. We might want to be more specific. 
    2. The class sent to this is a subclass of BaseResource, or another class. 
    3. Thus, we want to capture cases in which it is an appropriate instance, and respond. 
    """

    def handle_save(self, sender, instance, **kwargs):
        """
        Given an individual model instance, determine which backends the
        update should be sent to & update the object on those backends.
        """
        from hs_core.models import BaseResource
        from hs_access_control.models import ResourceAccess

        if isinstance(instance, BaseResource):
            if hasattr(instance, 'raccess') and hasattr(instance, 'metadata'):
                # work around for failure of super(BaseResource, instance) to work properly.
                # this always succeeds because this is a post-save object action.
                newbase = BaseResource.objects.get(pk=instance.pk)
                newsender = BaseResource
                using_backends = self.connection_router.for_write(instance=newbase)
                for using in using_backends:
                    # if object is public/discoverable or becoming public/discoverable, index it
                    # test whether the object should be exposed.
                    if instance.show_in_discover:
                        try:
                            index = self.connections[using].get_unified_index().get_index(newsender)
                            index.update_object(newbase, using=using)
                        except NotHandled:
                            logger.exception("Failure: changes to %s with short_id %s not added to Solr Index.",
                                             str(type(instance)), newbase.short_id)


                    # if object is private or becoming private, delete from index
                    else:  # not to be shown in discover
                        try:
                            index = self.connections[using].get_unified_index().get_index(newsender)
                            index.remove_object(newbase, using=using)
                        except NotHandled:
                            logger.exception("Failure: delete of %s with short_id %s failed.",
                                             str(type(instance)), newbase.short_id)

        elif isinstance(instance, ResourceAccess):
            # automatically a BaseResource; just call the routine on it.
            try:
                newbase = instance.resource
                self.handle_save(BaseResource, newbase)
            except Exception as e:
                logger.error("ResourceAccess id={} exception: {}".format(instance.id, e.message))

        elif isinstance(instance, CoreMetaData):
            try:
                newbase = instance.resource
                self.handle_save(BaseResource, newbase)
            except Exception:
                logger.error("CoreMetaData id={} exception: {}".format(instance.id, e.message))

        elif isinstance(instance, AbstractMetaDataElement):
            try:
                # resolve the BaseResource corresponding to the metadata element.
                # fields used here are the union of all fields in the metadata element
                # some of these are deprecated, but in the interest of time,
                # I included them now and will delete later.
                newbase = instance.metadata.resource
                self.handle_save(BaseResource, newbase)
            except Exception as e:
                print("{} {} exception: {}".format(type(instance), instance.id, e.message))

        else:  # could be extended metadata element
            try:
                newbase = BaseResource.objects.get(extra_metadata=instance)
                self.handle_save(BaseResource, newbase)
            except Exception as e:
                print("{} {} exception: {}".format(type(instance), instance.id, e.message))

    def handle_delete(self, sender, instance, **kwargs):
        """
        Ignore delete events as this is accomplished separately. 
        """
        pass

@@ -989,32 +989,71 @@
 ort BaseResource
+, CoreMetaData, AbstractMetaDataElement
 %0A        from hs
@@ -3683,233 +3683,8 @@
 nt.%0A
-                # fields used here are the union of all fields in the metadata element%0A                # some of these are deprecated, but in the interest of time,%0A                # I included them now and will delete later.%0A
     

Add references to base libraries