Skip to content

Commit

Permalink
allow multiple object adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
hahn-kev committed Oct 15, 2024
1 parent e767624 commit 8b1237e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 19 deletions.
8 changes: 6 additions & 2 deletions src/SIL.Harmony/Adapters/CustomAdapterProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ public class CustomAdapterProvider<TCommonInterface, TCustomAdapter> : IObjectAd
{
private readonly ObjectTypeListBuilder _objectTypeListBuilder;
private readonly List<AdapterRegistration> _objectTypes = new();
private Dictionary<Type, List<JsonDerivedType>> JsonTypes { get; } = [];
Dictionary<Type, List<JsonDerivedType>> IObjectAdapterProvider.JsonTypes => JsonTypes;
private Dictionary<Type, List<JsonDerivedType>> JsonTypes => _objectTypeListBuilder.JsonTypes;

public CustomAdapterProvider(ObjectTypeListBuilder objectTypeListBuilder)
{
Expand Down Expand Up @@ -55,6 +54,11 @@ IObjectBase IObjectAdapterProvider.Adapt(object obj)
{
return TCustomAdapter.Create((TCommonInterface)obj);
}

public bool CanAdapt(object obj)
{
return obj is TCommonInterface;
}
}

// it's possible to implement this without a Common interface
Expand Down
8 changes: 6 additions & 2 deletions src/SIL.Harmony/Adapters/DefaultAdapterProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ IObjectBase IObjectAdapterProvider.Adapt(object obj)
$"Object is of type {obj.GetType().Name} which does not implement {nameof(IObjectBase)}");
}

private Dictionary<Type, List<JsonDerivedType>> JsonTypes { get; } = [];
Dictionary<Type, List<JsonDerivedType>> IObjectAdapterProvider.JsonTypes => JsonTypes;
public bool CanAdapt(object obj)
{
return obj is IObjectBase;
}

private Dictionary<Type, List<JsonDerivedType>> JsonTypes => objectTypeListBuilder.JsonTypes;
}
3 changes: 1 addition & 2 deletions src/SIL.Harmony/Adapters/IObjectAdapterProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@ internal interface IObjectAdapterProvider
{
IEnumerable<AdapterRegistration> GetRegistrations();
IObjectBase Adapt(object obj);

Dictionary<Type, List<JsonDerivedType>> JsonTypes { get; }
bool CanAdapt(object obj);
}
41 changes: 28 additions & 13 deletions src/SIL.Harmony/CrdtConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ public void AddRemoteResourceEntity(string? cachePath = null)
{
RemoteResourcesEnabled = true;
LocalResourceCachePath = cachePath ?? LocalResourceCachePath;
ObjectTypeListBuilder.Add<RemoteResource>();
ObjectTypeListBuilder.DefaultAdapter().Add<RemoteResource>();
ChangeTypeListBuilder.Add<RemoteResourceUploadedChange>();
ChangeTypeListBuilder.Add<CreateRemoteResourceChange>();
ChangeTypeListBuilder.Add<CreateRemoteResourcePendingUploadChange>();
ChangeTypeListBuilder.Add<DeleteChange<RemoteResource>>();
ObjectTypeListBuilder.AddDbModelConfig(builder =>
ObjectTypeListBuilder.ModelConfigurations.Add((builder, config) =>
{
var entity = builder.Entity<LocalResource>();
entity.HasKey(lr => lr.Id);
Expand Down Expand Up @@ -127,8 +127,7 @@ public void Freeze()
{
if (_frozen) return;
_frozen = true;
JsonTypes = AdapterProvider.JsonTypes;
foreach (var registration in AdapterProvider.GetRegistrations())
foreach (var registration in AdapterProviders.SelectMany(a => a.GetRegistrations()))
{
ModelConfigurations.Add((builder, config) =>
{
Expand All @@ -147,19 +146,18 @@ internal void CheckFrozen()
if (_frozen) throw new InvalidOperationException($"{nameof(ObjectTypeListBuilder)} is frozen");
}

internal Dictionary<Type, List<JsonDerivedType>>? JsonTypes { get; set; }
internal Dictionary<Type, List<JsonDerivedType>> JsonTypes { get; } = [];

internal List<Action<ModelBuilder, CrdtConfig>> ModelConfigurations { get; } = [];

internal IObjectAdapterProvider AdapterProvider => _adapterProvider ?? throw new InvalidOperationException("No adapter has been added to the builder");
private IObjectAdapterProvider? _adapterProvider;
internal List<IObjectAdapterProvider> AdapterProviders { get; } = [];

public DefaultAdapterProvider DefaultAdapter()
{
CheckFrozen();
if (_adapterProvider is not null) throw new InvalidOperationException("adapter has already been added");
var adapter = new DefaultAdapterProvider(this);
_adapterProvider = adapter;
if (AdapterProviders.OfType<DefaultAdapterProvider>().SingleOrDefault() is {} adapter) return adapter;
adapter = new DefaultAdapterProvider(this);
AdapterProviders.Add(adapter);
return adapter;
}

Expand All @@ -182,9 +180,26 @@ public CustomAdapterProvider<TCommonInterface, TAdapter> CustomAdapter<TCommonIn
where TCommonInterface : class where TAdapter : class, ICustomAdapter<TAdapter, TCommonInterface>, IPolyType
{
CheckFrozen();
if (_adapterProvider is not null) throw new InvalidOperationException("adapter has already been added");
var adapter = new CustomAdapterProvider<TCommonInterface, TAdapter>(this);
_adapterProvider = adapter;
if (AdapterProviders.OfType<CustomAdapterProvider<TCommonInterface, TAdapter>>().SingleOrDefault() is {} adapter) return adapter;
adapter = new CustomAdapterProvider<TCommonInterface, TAdapter>(this);
AdapterProviders.Add(adapter);
return adapter;
}

internal IObjectBase Adapt(object obj)
{
if (AdapterProviders is [{ } defaultAdapter])
{
return defaultAdapter.Adapt(obj);
}

foreach (var objectAdapterProvider in AdapterProviders)
{
if (objectAdapterProvider.CanAdapt(obj))
{
return objectAdapterProvider.Adapt(obj);
}
}
throw new ArgumentException($"Unable to adapt object of type {obj.GetType()}");
}
}

0 comments on commit 8b1237e

Please sign in to comment.