215 lines
8.0 KiB
C#
215 lines
8.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace MxGateway.Worker.MxAccess;
|
|
|
|
public sealed class MxAccessHandleRegistry
|
|
{
|
|
private readonly Dictionary<int, RegisteredServerHandle> serverHandles = new();
|
|
private readonly Dictionary<long, RegisteredItemHandle> itemHandles = new();
|
|
private readonly Dictionary<AdviceHandleKey, RegisteredAdviceHandle> adviceHandles = new();
|
|
|
|
/// <summary>Gets a read-only list of registered server handles ordered by handle value.</summary>
|
|
public IReadOnlyList<RegisteredServerHandle> ServerHandles => serverHandles
|
|
.Values
|
|
.OrderBy(handle => handle.ServerHandle)
|
|
.ToArray();
|
|
|
|
/// <summary>Gets a read-only list of registered item handles ordered by server handle then item handle.</summary>
|
|
public IReadOnlyList<RegisteredItemHandle> ItemHandles => itemHandles
|
|
.Values
|
|
.OrderBy(handle => handle.ServerHandle)
|
|
.ThenBy(handle => handle.ItemHandle)
|
|
.ToArray();
|
|
|
|
/// <summary>Gets a read-only list of registered advice handles ordered by server handle, item handle, and advice kind.</summary>
|
|
public IReadOnlyList<RegisteredAdviceHandle> AdviceHandles => adviceHandles
|
|
.Values
|
|
.OrderBy(handle => handle.ServerHandle)
|
|
.ThenBy(handle => handle.ItemHandle)
|
|
.ThenBy(handle => handle.AdviceKind)
|
|
.ToArray();
|
|
|
|
/// <summary>Registers a server handle with the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="clientName">Display name of the client that owns the server handle.</param>
|
|
public void RegisterServerHandle(
|
|
int serverHandle,
|
|
string clientName)
|
|
{
|
|
serverHandles[serverHandle] = new RegisteredServerHandle(serverHandle, clientName);
|
|
}
|
|
|
|
/// <summary>Unregisters a server handle and all associated item and advice handles from the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
public void UnregisterServerHandle(int serverHandle)
|
|
{
|
|
serverHandles.Remove(serverHandle);
|
|
|
|
foreach (long key in itemHandles
|
|
.Where(pair => pair.Value.ServerHandle == serverHandle)
|
|
.Select(pair => pair.Key)
|
|
.ToArray())
|
|
{
|
|
itemHandles.Remove(key);
|
|
}
|
|
|
|
foreach (AdviceHandleKey key in adviceHandles
|
|
.Where(pair => pair.Value.ServerHandle == serverHandle)
|
|
.Select(pair => pair.Key)
|
|
.ToArray())
|
|
{
|
|
adviceHandles.Remove(key);
|
|
}
|
|
}
|
|
|
|
/// <summary>Checks if the registry contains the specified server handle.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
public bool ContainsServerHandle(int serverHandle)
|
|
{
|
|
return serverHandles.ContainsKey(serverHandle);
|
|
}
|
|
|
|
/// <summary>Registers an item handle with the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemDefinition">Item definition name from MXAccess.</param>
|
|
/// <param name="itemContext">Item context from MXAccess, or empty string if none.</param>
|
|
/// <param name="hasItemContext">True if the item has a context; false otherwise.</param>
|
|
public void RegisterItemHandle(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
string itemDefinition,
|
|
string itemContext,
|
|
bool hasItemContext)
|
|
{
|
|
itemHandles[CreateItemKey(serverHandle, itemHandle)] = new RegisteredItemHandle(
|
|
serverHandle,
|
|
itemHandle,
|
|
itemDefinition,
|
|
itemContext,
|
|
hasItemContext);
|
|
}
|
|
|
|
/// <summary>Removes an item handle and all associated advice handles from the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
public void RemoveItemHandle(
|
|
int serverHandle,
|
|
int itemHandle)
|
|
{
|
|
itemHandles.Remove(CreateItemKey(serverHandle, itemHandle));
|
|
RemoveAdviceHandles(serverHandle, itemHandle);
|
|
}
|
|
|
|
/// <summary>Checks if the registry contains the specified item handle.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
public bool ContainsItemHandle(
|
|
int serverHandle,
|
|
int itemHandle)
|
|
{
|
|
return itemHandles.ContainsKey(CreateItemKey(serverHandle, itemHandle));
|
|
}
|
|
|
|
/// <summary>Registers an advice handle with the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
/// <param name="adviceKind">Type of advice to register.</param>
|
|
public void RegisterAdviceHandle(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
MxAccessAdviceKind adviceKind)
|
|
{
|
|
AdviceHandleKey key = new(serverHandle, itemHandle, adviceKind);
|
|
adviceHandles[key] = new RegisteredAdviceHandle(
|
|
serverHandle,
|
|
itemHandle,
|
|
adviceKind);
|
|
}
|
|
|
|
/// <summary>Removes all advice handles for the specified server and item handles from the registry.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
public void RemoveAdviceHandles(
|
|
int serverHandle,
|
|
int itemHandle)
|
|
{
|
|
foreach (AdviceHandleKey key in adviceHandles
|
|
.Where(pair => pair.Value.ServerHandle == serverHandle && pair.Value.ItemHandle == itemHandle)
|
|
.Select(pair => pair.Key)
|
|
.ToArray())
|
|
{
|
|
adviceHandles.Remove(key);
|
|
}
|
|
}
|
|
|
|
/// <summary>Checks if the registry contains the specified advice handle.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
/// <param name="adviceKind">Type of advice to check.</param>
|
|
public bool ContainsAdviceHandle(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
MxAccessAdviceKind adviceKind)
|
|
{
|
|
return adviceHandles.ContainsKey(new AdviceHandleKey(serverHandle, itemHandle, adviceKind));
|
|
}
|
|
|
|
private static long CreateItemKey(
|
|
int serverHandle,
|
|
int itemHandle)
|
|
{
|
|
return ((long)serverHandle << 32) | (uint)itemHandle;
|
|
}
|
|
|
|
private readonly struct AdviceHandleKey : IEquatable<AdviceHandleKey>
|
|
{
|
|
private readonly int serverHandle;
|
|
private readonly int itemHandle;
|
|
private readonly MxAccessAdviceKind adviceKind;
|
|
|
|
/// <summary>Initializes a new instance of the <see cref="AdviceHandleKey"/> struct.</summary>
|
|
/// <param name="serverHandle">Handle returned by the worker.</param>
|
|
/// <param name="itemHandle">Handle returned by the worker.</param>
|
|
/// <param name="adviceKind">Type of advice.</param>
|
|
public AdviceHandleKey(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
MxAccessAdviceKind adviceKind)
|
|
{
|
|
this.serverHandle = serverHandle;
|
|
this.itemHandle = itemHandle;
|
|
this.adviceKind = adviceKind;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public bool Equals(AdviceHandleKey other)
|
|
{
|
|
return serverHandle == other.serverHandle
|
|
&& itemHandle == other.itemHandle
|
|
&& adviceKind == other.adviceKind;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return obj is AdviceHandleKey other && Equals(other);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
int hashCode = serverHandle;
|
|
hashCode = (hashCode * 397) ^ itemHandle;
|
|
hashCode = (hashCode * 397) ^ (int)adviceKind;
|
|
|
|
return hashCode;
|
|
}
|
|
}
|
|
}
|
|
}
|