Skip to content

Commit 26c1e52

Browse files
committed
Continue Repository Base Setup
1 parent b6f5528 commit 26c1e52

10 files changed

Lines changed: 285 additions & 2 deletions

File tree

PG.Commons/PG.Commons/Data/IId.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace PG.Commons.Data;
4+
5+
/// <summary>
6+
/// A generic ID definition
7+
/// </summary>
8+
public interface IId : IEquatable<IId>
9+
{
10+
/// <summary>
11+
/// The arity of the ID.
12+
/// </summary>
13+
int Arity { get; }
14+
15+
/// <summary>
16+
/// The string representation of the ID
17+
/// </summary>
18+
/// <returns></returns>
19+
string Unwrap();
20+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Linq;
3+
using System.Text;
4+
using PG.Commons.Exceptions;
5+
6+
namespace PG.Commons.Data;
7+
8+
/// <inheritdoc />
9+
public abstract class IdBase : IId
10+
{
11+
/// <summary>
12+
/// The ID components.
13+
/// </summary>
14+
protected readonly object?[] Components;
15+
16+
/// <summary>
17+
/// .ctor
18+
/// </summary>
19+
protected IdBase(params object[] components)
20+
{
21+
if (components.Length != Arity) throw new ArgumentException("Invalid number of components");
22+
Components = new object[Arity];
23+
for (var i = 0; i < Components.Length; i++) Components[i] = components[i];
24+
}
25+
26+
/// <inheritdoc />
27+
public bool Equals(IId? other)
28+
{
29+
return other != null && Arity == other.Arity && GetHashCode().Equals(other.GetHashCode());
30+
}
31+
32+
/// <inheritdoc />
33+
public int Arity => GetConfiguredArity();
34+
35+
/// <inheritdoc />
36+
public string Unwrap()
37+
{
38+
var b = new StringBuilder();
39+
b.Append(GetType().Name).Append('[');
40+
foreach (var idComponent in Components) b.Append(idComponent).Append(';');
41+
b.Remove(b.Length - 1, 1); // remove the last ";".
42+
b.Append(']');
43+
return b.ToString();
44+
}
45+
46+
/// <summary>
47+
/// Convenience method to access components in a type-safe manner.
48+
/// </summary>
49+
/// <param name="idx"></param>
50+
/// <param name="type"></param>
51+
/// <typeparam name="T"></typeparam>
52+
/// <returns></returns>
53+
/// <exception cref="ArgumentException">If the provided index is out of bounds.</exception>
54+
/// <exception cref="ArgumentNullException">If no <see cref="Type" /> is provided.</exception>
55+
/// <exception cref="Exception"></exception>
56+
protected T? GetIdComponent<T>(int idx, Type type) where T : class
57+
{
58+
if (idx > 0 || idx >= Arity) throw new ArgumentException("Invalid component index");
59+
if (type == null) throw new ArgumentNullException(nameof(type));
60+
var c = Components[idx];
61+
if (c?.GetType() != type) throw new TypeMismatchException($"Component {idx - 1} is not of type {type}");
62+
return c as T;
63+
}
64+
65+
/// <inheritdoc />
66+
public override int GetHashCode()
67+
{
68+
return HashCode.Combine(GetConfiguredArity(), HashCode.Combine(Components));
69+
}
70+
71+
/// <summary>
72+
/// Returns true if this ID is equivalent to null.
73+
/// </summary>
74+
/// <returns></returns>
75+
protected virtual bool IsNullId()
76+
{
77+
return Components.Any();
78+
}
79+
80+
/// <summary>
81+
/// The arity of this ID type.
82+
/// </summary>
83+
/// <returns></returns>
84+
protected abstract int GetConfiguredArity();
85+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
3+
namespace PG.Commons.Data;
4+
5+
/// <inheritdoc cref="PG.Commons.Data.IdBase" />
6+
public abstract class RootIdBase<T> : IdBase, IComparable<RootIdBase<T>> where T : class, IComparable<T>
7+
{
8+
/// <inheritdoc />
9+
protected RootIdBase(T rawId) : base(rawId)
10+
{
11+
}
12+
13+
/// <inheritdoc />
14+
public int CompareTo(RootIdBase<T>? other)
15+
{
16+
return other == null ? 1 : Raw().CompareTo(other.Raw());
17+
}
18+
19+
/// <inheritdoc />
20+
protected override int GetConfiguredArity()
21+
{
22+
return 1;
23+
}
24+
25+
/// <inheritdoc />
26+
protected override bool IsNullId()
27+
{
28+
return Components[0] == null;
29+
}
30+
31+
/// <summary>
32+
/// Raw value.
33+
/// </summary>
34+
/// <returns></returns>
35+
/// <exception cref="InvalidOperationException"></exception>
36+
public T Raw()
37+
{
38+
return Components[0] as T ?? throw new InvalidOperationException();
39+
}
40+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
3+
namespace PG.Commons.Exceptions;
4+
5+
/// <summary>
6+
/// Thrown if the provided type does not match the requested type. Usually thrown when a generic request for a key
7+
/// component is not logically sound.
8+
/// </summary>
9+
public class TypeMismatchException : Exception
10+
{
11+
/// <inheritdoc />
12+
public TypeMismatchException()
13+
{
14+
}
15+
16+
/// <inheritdoc />
17+
public TypeMismatchException(string message) : base(message)
18+
{
19+
}
20+
21+
/// <inheritdoc />
22+
public TypeMismatchException(string message, Exception inner) : base(message, inner)
23+
{
24+
}
25+
}

PG.StarWarsGame.Components.Localisation/PG.StarWarsGame.Components.Localisation/Repository/Content/ITranslationItemContent.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ public interface ITranslationItemContent
1313
/// <summary>
1414
/// The string value, usually mapped to <see cref="PG.StarWarsGame.Files.DAT.Data.DatStringEntry.Value" />
1515
/// </summary>
16-
string Value { get; set; }
16+
string? Value { get; set; }
1717
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
using PG.Commons.Data;
2+
13
namespace PG.StarWarsGame.Components.Localisation.Repository.Content;
24

35
/// <summary>
46
/// The unique item ID, could be the string key, or any other unique ID.
57
/// </summary>
6-
public interface ITranslationItemId
8+
public interface ITranslationItemId : IId
79
{
810
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
3+
namespace PG.StarWarsGame.Components.Localisation.Repository.Content;
4+
5+
/// <inheritdoc />
6+
public class OrderedTranslationItem : TranslationItemBase
7+
{
8+
/// <inheritdoc />
9+
protected OrderedTranslationItem(OrderedTranslationItemId itemId, TranslationItemContent content,
10+
ITranslationItem.TranslationItemSource source, bool overwritten) : base(itemId, content, source, overwritten)
11+
{
12+
}
13+
14+
/// <summary>
15+
/// Convenience method to create a new <see cref="OrderedTranslationItem" />
16+
/// </summary>
17+
/// <param name="itemId"></param>
18+
/// <param name="content"></param>
19+
/// <param name="source"></param>
20+
/// <param name="overwritten"></param>
21+
/// <returns></returns>
22+
public static OrderedTranslationItem Of(OrderedTranslationItemId itemId, TranslationItemContent content,
23+
ITranslationItem.TranslationItemSource source, bool overwritten)
24+
{
25+
return new OrderedTranslationItem(itemId, content, source, overwritten);
26+
}
27+
28+
/// <summary>
29+
/// Convenience method to create a new <see cref="OrderedTranslationItem" />
30+
/// </summary>
31+
/// <param name="content"></param>
32+
/// <param name="source"></param>
33+
/// <param name="overwritten"></param>
34+
/// <returns></returns>
35+
/// <exception cref="InvalidOperationException"></exception>
36+
public static OrderedTranslationItem Of(TranslationItemContent content,
37+
ITranslationItem.TranslationItemSource source = ITranslationItem.TranslationItemSource.Mod,
38+
bool overwritten = false)
39+
{
40+
return Of(OrderedTranslationItemId.Of(content.Key) ?? throw new InvalidOperationException(), content, source,
41+
overwritten);
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using PG.Commons.Data;
2+
3+
namespace PG.StarWarsGame.Components.Localisation.Repository.Content;
4+
5+
/// <summary>
6+
/// Item ID for ordered translation items. Equivalent to the raw string key from a sorted DAT file.
7+
/// </summary>
8+
public class OrderedTranslationItemId : RootIdBase<string>, ITranslationItemId
9+
{
10+
/// <inheritdoc />
11+
protected OrderedTranslationItemId(string rawId) : base(rawId)
12+
{
13+
}
14+
15+
/// <summary>
16+
/// Convenience method to create a new <see cref="OrderedTranslationItemId" />
17+
/// </summary>
18+
/// <param name="rawId"></param>
19+
/// <returns></returns>
20+
public static OrderedTranslationItemId? Of(string rawId)
21+
{
22+
return string.IsNullOrWhiteSpace(rawId) ? null : new OrderedTranslationItemId(rawId);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
namespace PG.StarWarsGame.Components.Localisation.Repository.Content;
2+
3+
/// <inheritdoc />
4+
public abstract class TranslationItemBase : ITranslationItem
5+
{
6+
/// <summary>
7+
/// .ctor
8+
/// </summary>
9+
/// <param name="itemId"></param>
10+
/// <param name="content"></param>
11+
/// <param name="source"></param>
12+
/// <param name="overwritten"></param>
13+
protected TranslationItemBase(ITranslationItemId itemId, TranslationItemContent content,
14+
ITranslationItem.TranslationItemSource source, bool overwritten)
15+
{
16+
ItemId = itemId;
17+
Content = content;
18+
Source = source;
19+
Overwritten = overwritten;
20+
}
21+
22+
/// <inheritdoc />
23+
public ITranslationItemContent Content { get; set; }
24+
25+
/// <inheritdoc />
26+
public ITranslationItemId ItemId { get; }
27+
28+
/// <inheritdoc />
29+
public ITranslationItem.TranslationItemSource Source { get; }
30+
31+
/// <inheritdoc />
32+
public bool Overwritten { get; }
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace PG.StarWarsGame.Components.Localisation.Repository.Content;
2+
3+
/// <inheritdoc />
4+
public record TranslationItemContent : ITranslationItemContent
5+
{
6+
/// <inheritdoc />
7+
public required string Key { get; set; }
8+
9+
/// <inheritdoc />
10+
public string? Value { get; set; }
11+
}

0 commit comments

Comments
 (0)