# Path: djangoevents/domain.py
# class BaseEntity(BaseAggregate):
#     """
#     `EventSourcedEntity` with saner mutator routing:
# 
#     OBSOLETE! Interface kept for backward compatibility.
#     """
#     @classmethod
#     def is_abstract_class(cls):
#         return super().is_abstract_class() or cls is BaseEntity
# 
#     @classmethod
#     def mutate(cls, entity=None, event=None):
#         warnings.warn("`BaseEntity` is depreciated. Please switch to: `BaseAggregate`", DeprecationWarning)
#         return super().mutate(aggregate=entity, event=event)
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
#     """
#     `EventSourcedEntity` with saner mutator routing & naming:
# 
#     >>> class Asset(BaseAggregate):
#     >>>    class Created(BaseAggregate.Created):
#     >>>        def mutate(event, klass):
#     >>>            return klass(...)
#     >>>
#     >>>    class Updated(DomainEvent):
#     >>>        def mutate(event, instance):
#     >>>            instance.connect = True
#     >>>            return instance
#     """
# 
#     @classmethod
#     def is_abstract_class(cls):
#         return is_abstract(cls)
# 
#     @classmethod
#     def mutate(cls, aggregate=None, event=None):
#         if aggregate:
#             aggregate._validate_originator(event)
# 
#         if not hasattr(event, 'mutate_event'):
#             msg = "{} does not provide a mutate_event() method.".format(event.__class__)
#             raise NotImplementedError(msg)
# 
#         aggregate = event.mutate_event(event, aggregate or cls)
#         aggregate._increment_version()
#         return aggregate
# 
#     @classmethod
#     def create_for_event(cls, event):
#         aggregate = cls(
#             entity_id=event.entity_id,
#             domain_event_id=event.domain_event_id,
#             entity_version=event.entity_version,
#         )
#         return aggregate
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
# class BaseEntity(BaseAggregate):
#     def is_abstract_class(cls):
#     def mutate(cls, aggregate=None, event=None):
#     def create_for_event(cls, event):
#     def is_abstract_class(cls):
#     def mutate(cls, entity=None, event=None):
# 
# Path: djangoevents/utils_abstract.py
# def is_abstract(cls):
#     return cls in _abstract_classes


import inspect
import re
from .domain import BaseEntity
from .domain import BaseAggregate
from .domain import DomainEvent
from djangoevents.utils_abstract import is_abstract


def list_concrete_aggregates():
    """
    Lists all non abstract aggregates defined within the application.
    """
    aggregates = set(_list_subclasses(BaseAggregate) + _list_subclasses(BaseEntity))
    return [aggregate for aggregate in aggregates if not aggregate.is_abstract_class()]


def is_event_mutating(event):
    return hasattr(event, 'mutate_event')


def list_aggregate_events(aggregate_cls):
    """
    Lists all aggregate_cls events defined within the application.
    Note: Only events with a defined `mutate_event` flow and are not marked as abstract will be returned.
    """
    events = _list_internal_classes(aggregate_cls, DomainEvent)

# Path: djangoevents/domain.py
# class BaseEntity(BaseAggregate):
#     """
#     `EventSourcedEntity` with saner mutator routing:
# 
#     OBSOLETE! Interface kept for backward compatibility.
#     """
#     @classmethod
#     def is_abstract_class(cls):
#         return super().is_abstract_class() or cls is BaseEntity
# 
#     @classmethod
#     def mutate(cls, entity=None, event=None):
#         warnings.warn("`BaseEntity` is depreciated. Please switch to: `BaseAggregate`", DeprecationWarning)
#         return super().mutate(aggregate=entity, event=event)
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
#     """
#     `EventSourcedEntity` with saner mutator routing & naming:
# 
#     >>> class Asset(BaseAggregate):
#     >>>    class Created(BaseAggregate.Created):
#     >>>        def mutate(event, klass):
#     >>>            return klass(...)
#     >>>
#     >>>    class Updated(DomainEvent):
#     >>>        def mutate(event, instance):
#     >>>            instance.connect = True
#     >>>            return instance
#     """
# 
#     @classmethod
#     def is_abstract_class(cls):
#         return is_abstract(cls)
# 
#     @classmethod
#     def mutate(cls, aggregate=None, event=None):
#         if aggregate:
#             aggregate._validate_originator(event)
# 
#         if not hasattr(event, 'mutate_event'):
#             msg = "{} does not provide a mutate_event() method.".format(event.__class__)
#             raise NotImplementedError(msg)
# 
#         aggregate = event.mutate_event(event, aggregate or cls)
#         aggregate._increment_version()
#         return aggregate
# 
#     @classmethod
#     def create_for_event(cls, event):
#         aggregate = cls(
#             entity_id=event.entity_id,
#             domain_event_id=event.domain_event_id,
#             entity_version=event.entity_version,
#         )
#         return aggregate
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
# class BaseEntity(BaseAggregate):
#     def is_abstract_class(cls):
#     def mutate(cls, aggregate=None, event=None):
#     def create_for_event(cls, event):
#     def is_abstract_class(cls):
#     def mutate(cls, entity=None, event=None):
# 
# Path: djangoevents/utils_abstract.py
# def is_abstract(cls):
#     return cls in _abstract_classes


# Path: djangoevents/utils.py
import inspect
import re
from .domain import BaseEntity
from .domain import BaseAggregate
from .domain import DomainEvent
from djangoevents.utils_abstract import is_abstract



def list_concrete_aggregates():
    """
    Lists all non abstract aggregates defined within the application.
    """
    aggregates = set(_list_subclasses(BaseAggregate) + _list_subclasses(BaseEntity))
    return [aggregate for aggregate in aggregates if not aggregate.is_abstract_class()]


def is_event_mutating(event):
    return hasattr(event, 'mutate_event')


def list_aggregate_events(aggregate_cls):
    """
    Lists all aggregate_cls events defined within the application.
    Note: Only events with a defined `mutate_event` flow and are not marked as abstract will be returned.
    """
    events = _list_internal_classes(aggregate_cls, DomainEvent)

    return [event_cls for event_cls in events if is_event_mutating(event_cls) and not is_abstract(event_cls)]