@startuml

    !include ../lexakai.theme
    
    title "Service Registry"
    
    abstract BaseServiceRegistry
    abstract BaseRepeater
    
    interface ServiceRegistry
    
    BaseRepeater <|-- BaseServiceRegistry
    ServiceRegistry <|-- BaseServiceRegistry
    -abstract class BaseServiceRegistry
    {
        --(constructors)--
        +BaseServiceRegistry()
        --(service)--
        +ServiceRegistry load()
        +BaseServiceRegistry updater(ServiceRegistryUpdater)
    }
    
    BaseServiceRegistry <|-- LocalServiceRegistry
    -class LocalServiceRegistry
    {
        --(constructors)--
        #LocalServiceRegistry()
        +LocalServiceRegistry(int)
    }
    
    BaseServiceRegistry <|-- NetworkServiceRegistry
    -class NetworkServiceRegistry
    {
    }
    
    Scope o-- Scope.Type
    Scope o-- ClusterIdentifier
    class Scope
    {
        --(constructors)--
        #Scope()
        #Scope(Type, ClusterIdentifier)
        --
        +Scope cluster(ClusterIdentifier)
        +Set<Scope> scopes(Result<Set<Service>>)
        +Type type()
        --(checks)--
        +boolean isCluster()
        +boolean isLocal()
        --(collection)--
        +List<String> names(Result<Set<Service>>)
        --(identity)--
        +ClusterIdentifier cluster()
        --(network)--
        +boolean isNetwork()
        +Scope localhost()
        +Scope network()
    }
    
    Service o-- ApplicationIdentifier
    Service o-- Scope : "visibility"
    Service o-- ServiceMetadata
    Service o-- ServiceType : "provided service"
    Service o-- Port : "allocated port"
    Service o-- JavaVirtualMachineHealth : "health status"
    class Service
    {
        --(constructors)--
        +Service()
        --
        +String descriptor()
        +JavaVirtualMachineHealth health()
        +Scope scope()
        --(checks)--
        +boolean isBound()
        +boolean isSame(Service that)
        +boolean isStale()
        +boolean isUnbound()
        --(identity)--
        +ApplicationIdentifier application()
        --(network)--
        +String hostAndApplication()
        +String hostApplicationAndPort()
        +Port port()
        --(service)--
        +Service application(ApplicationIdentifier)
        +Service health(JavaVirtualMachineHealth)
        +ServiceMetadata metadata()
        +Service metadata(ServiceMetadata)
        +Service port(Port)
        +Service renewedAt(Time renewedAt)
        +Service scope(Scope)
        +Service type(ServiceType)
        +ServiceType type()
        --(time)--
        +Time renewedAt()
    }
    
    ServiceMetadata o-- Version : "service version"
    ServiceMetadata o-- Version : "kivakit version"
    ServiceMetadata o-- EmailAddress : "contact email"
    class ServiceMetadata
    {
        --
        +String description()
        --(identity)--
        +Version kivakitVersion()
        +Version version()
        --(metadata)--
        +ServiceMetadata contactEmail(EmailAddress contactEmail)
        +ServiceMetadata description(String description)
        +ServiceMetadata kivakitVersion(Version)
        +ServiceMetadata version(Version)
        --(network)--
        +EmailAddress contactEmail()
    }
    
    interface Repeater
    Repeater <|-- ServiceRegistry
    note right of ServiceRegistry
        Use ServiceRegistryClient to register and discover services
    endnote
    -interface ServiceRegistry
    {
        --(checks)--
        +boolean isLocal()
        --(collection)--
        +Result<Boolean> addOrUpdate(Service)
        --(network)--
        +Result<Set<Host>> discoverHosts()
        +boolean isNetwork()
        +Port local()
        +Port network()
        +Port port(Host)
        --(search)--
        +Result<Set<ApplicationIdentifier>> discoverApplications(Scope)
        --(service)--
        +Result<Service> discoverPortService(Port)
        +Result<Set<Service>> discoverServices()
        +Result<Set<Service>> discoverServices(ServiceType)
        +Result<Set<Service>> discoverServices(ApplicationIdentifier)
        +Result<Set<Service>> discoverServices(ApplicationIdentifier, ServiceType)
        +Result<Service> register(Service)
        +Result<Service> renew(Service)
        +ServiceRegistrySettings settings()
    }
    
    BaseRepeater <|-- ServiceRegistryStore
    ServiceRegistryStore --> ServiceRegistry : "loads"
    -class ServiceRegistryStore
    {
        --(service)--
        +ServiceRegistry load(Class<? extends ServiceRegistry> type)
        --(write)--
        +void save(ServiceRegistry)
    }
    
    class ServiceType
    {
        --(constructors)--
        #ServiceType()
        +ServiceType(String)
    }
    
    enum Scope.Type
    {
        CLUSTER
        LOCALHOST
        NETWORK
    }
    
@enduml

