diff --git a/Source/ActivityPub.Types/AS/APActor.cs b/Source/ActivityPub.Types/AS/APActor.cs index ab8bdd0..cc2578e 100644 --- a/Source/ActivityPub.Types/AS/APActor.cs +++ b/Source/ActivityPub.Types/AS/APActor.cs @@ -4,10 +4,8 @@ using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; -using ActivityPub.Types.Conversion.Overrides; using ActivityPub.Types.Internal; using ActivityPub.Types.Util; -using JetBrains.Annotations; namespace ActivityPub.Types.AS; @@ -22,11 +20,11 @@ namespace ActivityPub.Types.AS; public class APActor : ASObject, IASModel { /// - public APActor() => Entity = TypeMap.Extend(); + public APActor() => Entity = TypeMap.Extend(); /// public APActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public APActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -35,7 +33,7 @@ public APActor(ASType existingGraph) : this(existingGraph.TypeMap) {} [SetsRequiredMembers] public APActor(TypeMap typeMap, APActorEntity? entity) : base(typeMap, null) { - Entity = entity ?? typeMap.AsEntity(); + Entity = entity ?? typeMap.AsEntity(); Inbox = Entity.Inbox ?? throw new ArgumentException($"The provided entity is invalid - required {nameof(APActorEntity.Inbox)} property is missing"); Outbox = Entity.Outbox ?? throw new ArgumentException($"The provided entity is invalid - required {nameof(APActorEntity.Outbox)} property is missing"); } @@ -134,10 +132,21 @@ public Linkable? Endpoints get => Entity.Endpoints; set => Entity.Endpoints = value; } + + /// + static bool? IASModel.ShouldConvertFrom(JsonElement inputJson, TypeMap typeMap) + { + if (inputJson.ValueKind != JsonValueKind.Object) + return false; + + return + inputJson.HasProperty("inbox") && + inputJson.HasProperty("outbox"); + } } /// -public sealed class APActorEntity : ASEntity, IAnonymousEntity +public sealed class APActorEntity : ASEntity { /// [JsonPropertyName("inbox")] @@ -170,56 +179,83 @@ public sealed class APActorEntity : ASEntity, IAnonymous /// [JsonPropertyName("endpoints")] public Linkable? Endpoints { get; set; } - - /// - public static bool ShouldConvertFrom(JsonElement inputJson, DeserializationMetadata meta) - { - if (inputJson.ValueKind != JsonValueKind.Object) - return false; - - return - inputJson.HasProperty("inbox") && - inputJson.HasProperty("outbox"); - } } /// /// A json object which maps additional (typically server/domain-wide) endpoints which may be useful for an actor. /// /// -[UsedImplicitly(ImplicitUseKindFlags.InstantiatedWithFixedConstructorSignature, ImplicitUseTargetFlags.WithMembers)] -public class ActorEndpoints +public class ActorEndpoints : ASType, IASModel { + /// + public ActorEndpoints() => Entity = TypeMap.Extend(); + + /// + public ActorEndpoints(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) + => Entity = TypeMap.ProjectTo(isExtending); + + /// + public ActorEndpoints(ASType existingGraph) : this(existingGraph.TypeMap) {} + + /// + [SetsRequiredMembers] + public ActorEndpoints(TypeMap typeMap, ActorEndpointsEntity? entity) : base(typeMap, null) + => Entity = entity ?? typeMap.AsEntity(); + + static ActorEndpoints IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); + + private ActorEndpointsEntity Entity { get; } + /// /// Endpoint URI so this actor's clients may access remote ActivityStreams objects which require authentication to access. /// To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value being the id of the requested ActivityStreams object. /// [JsonPropertyName("proxyUrl")] - public ASLink? ProxyUrl { get; set; } + public ASLink? ProxyUrl + { + get => Entity.ProxyUrl; + set => Entity.ProxyUrl = value; + } /// /// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a browser-authenticated user may obtain a new authorization grant. /// [JsonPropertyName("oauthAuthorizationEndpoint")] - public ASLink? OAuthAuthorizationEndpoint { get; set; } + public ASLink? OAuthAuthorizationEndpoint + { + get => Entity.OAuthAuthorizationEndpoint; + set => Entity.OAuthAuthorizationEndpoint = value; + } /// /// If OAuth 2.0 bearer tokens [RFC6749] [RFC6750] are being used for authenticating client to server interactions, this endpoint specifies a URI at which a client may acquire an access token. /// [JsonPropertyName("oauthTokenEndpoint")] - public ASLink? OAuthTokenEndpoint { get; set; } + public ASLink? OAuthTokenEndpoint + { + get => Entity.OAuthTokenEndpoint; + set => Entity.OAuthTokenEndpoint = value; + } /// /// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which browser-authenticated users may authorize a client's public key for client to server interactions. /// [JsonPropertyName("provideClientKey")] - public ASLink? ProvideClientKey { get; set; } + public ASLink? ProvideClientKey + { + get => Entity.ProvideClientKey; + set => Entity.ProvideClientKey = value; + } /// /// If Linked Data Signatures and HTTP Signatures are being used for authentication and authorization, this endpoint specifies a URI at which a client key may be signed by the actor's key for a time window to act on behalf of the actor in interacting with foreign servers. /// [JsonPropertyName("signClientKey")] - public ASLink? SignClientKey { get; set; } + public ASLink? SignClientKey + { + get => Entity.SignClientKey; + set => Entity.SignClientKey = value; + } /// /// An optional endpoint used for wide delivery of publicly addressed activities and activities sent to followers. @@ -227,5 +263,37 @@ public class ActorEndpoints /// Reading from the sharedInbox endpoint MUST NOT present objects which are not addressed to the Public endpoint. /// [JsonPropertyName("sharedInbox")] + public ASLink? SharedInbox + { + get => Entity.SharedInbox; + set => Entity.SharedInbox = value; + } +} + +/// +public sealed class ActorEndpointsEntity : ASEntity +{ + /// + [JsonPropertyName("proxyUrl")] + public ASLink? ProxyUrl { get; set; } + + /// + [JsonPropertyName("oauthAuthorizationEndpoint")] + public ASLink? OAuthAuthorizationEndpoint { get; set; } + + /// + [JsonPropertyName("oauthTokenEndpoint")] + public ASLink? OAuthTokenEndpoint { get; set; } + + /// + [JsonPropertyName("provideClientKey")] + public ASLink? ProvideClientKey { get; set; } + + /// + [JsonPropertyName("signClientKey")] + public ASLink? SignClientKey { get; set; } + + /// + [JsonPropertyName("sharedInbox")] public ASLink? SharedInbox { get; set; } } \ No newline at end of file diff --git a/Source/ActivityPub.Types/AS/ASActivity.cs b/Source/ActivityPub.Types/AS/ASActivity.cs index 26279cf..db9222d 100644 --- a/Source/ActivityPub.Types/AS/ASActivity.cs +++ b/Source/ActivityPub.Types/AS/ASActivity.cs @@ -24,11 +24,11 @@ public class ASActivity : ASObject, IASModel.ASTypeName => ActivityType; /// - public ASActivity() => Entity = TypeMap.Extend(); + public ASActivity() => Entity = TypeMap.Extend(); /// public ASActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -36,7 +36,7 @@ public ASActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ASActivity(TypeMap typeMap, ASActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/ASIntransitiveActivity.cs b/Source/ActivityPub.Types/AS/ASIntransitiveActivity.cs index 9f89eb1..68ae80c 100644 --- a/Source/ActivityPub.Types/AS/ASIntransitiveActivity.cs +++ b/Source/ActivityPub.Types/AS/ASIntransitiveActivity.cs @@ -22,11 +22,11 @@ public class ASIntransitiveActivity : ASActivity, IASModel.ASTypeName => IntransitiveActivityType; /// - public ASIntransitiveActivity() => Entity = TypeMap.Extend(); + public ASIntransitiveActivity() => Entity = TypeMap.Extend(); /// public ASIntransitiveActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASIntransitiveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public ASIntransitiveActivity(ASType existingGraph) : this(existingGraph.TypeMap /// [SetsRequiredMembers] public ASIntransitiveActivity(TypeMap typeMap, ASIntransitiveActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASIntransitiveActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/ASLink.cs b/Source/ActivityPub.Types/AS/ASLink.cs index 4673e94..9508c70 100644 --- a/Source/ActivityPub.Types/AS/ASLink.cs +++ b/Source/ActivityPub.Types/AS/ASLink.cs @@ -26,11 +26,11 @@ public class ASLink : ASType, IASModel static string IASModel.ASTypeName => LinkType; /// - public ASLink() => Entity = TypeMap.Extend(); + public ASLink() => Entity = TypeMap.Extend(); /// public ASLink(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASLink(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -39,7 +39,7 @@ public ASLink(ASType existingGraph) : this(existingGraph.TypeMap) {} [SetsRequiredMembers] public ASLink(TypeMap typeMap, ASLinkEntity? entity) : base(typeMap, null) { - Entity = entity ?? typeMap.AsEntity(); + Entity = entity ?? typeMap.AsEntity(); HRef = Entity.HRef ?? throw new ArgumentException($"The provided entity is invalid - required {nameof(ASLinkEntity.HRef)} property is missing"); } diff --git a/Source/ActivityPub.Types/AS/ASObject.cs b/Source/ActivityPub.Types/AS/ASObject.cs index 0480ad5..a7b0142 100644 --- a/Source/ActivityPub.Types/AS/ASObject.cs +++ b/Source/ActivityPub.Types/AS/ASObject.cs @@ -2,12 +2,9 @@ // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Nodes; using System.Text.Json.Serialization; using ActivityPub.Types.AS.Collection; using ActivityPub.Types.AS.Extended.Object; -using ActivityPub.Types.Conversion.Overrides; using ActivityPub.Types.Util; using JetBrains.Annotations; @@ -28,22 +25,22 @@ public class ASObject : ASType, IASModel static string IASModel.ASTypeName => ObjectType; /// - public ASObject() => Entity = TypeMap.Extend(); + public ASObject() => Entity = TypeMap.Extend(); /// public ASObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// /// Constructs a new instance and extends an existing type graph from a provided model. /// - /// + /// public ASObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ASObject(TypeMap typeMap, ASObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); @@ -222,8 +219,8 @@ public List Url /// public NaturalLanguageString? Content { - get => Entity.Content; - set => Entity.Content = value; + get => Entity.ContentMap; + set => Entity.ContentMap = value; } /// @@ -329,7 +326,7 @@ public Linkable? Shares } /// -public sealed class ASObjectEntity : ASEntity, ICustomConvertedEntity +public sealed class ASObjectEntity : ASEntity, IJsonOnDeserialized, IJsonOnSerializing { /// [JsonPropertyName("attachment")] @@ -393,7 +390,11 @@ public sealed class ASObjectEntity : ASEntity, ICustom /// [JsonPropertyName("contentMap")] - public NaturalLanguageString? Content { get; set; } + public NaturalLanguageString? ContentMap { get; set; } + + /// + [JsonPropertyName("content")] + public string? Content { get; set; } /// [JsonPropertyName("duration")] @@ -430,31 +431,25 @@ public sealed class ASObjectEntity : ASEntity, ICustom /// [JsonPropertyName("shares")] public Linkable? Shares { get; set; } - - static void ICustomConvertedEntity.PostReadEntity(JsonElement jsonElement, DeserializationMetadata meta, ASObjectEntity entity) + + // Sync up "content" and "contentMap" properties + void IJsonOnDeserialized.OnDeserialized() { - if (!jsonElement.TryGetProperty("content", out var contentProperty)) - return; - - var content = contentProperty.GetString(); - if (content == null) + if (Content == null) return; - entity.Content ??= new NaturalLanguageString(); - entity.Content.DefaultValue = content; + if (ContentMap == null) + ContentMap = Content; + else + ContentMap.DefaultValue = Content; } - - static void ICustomConvertedEntity.PostWriteEntity(ASObjectEntity entity, SerializationMetadata meta, JsonElement entityJson, JsonObject outputJson) + + // Sync up "content" and "contentMap" properties + void IJsonOnSerializing.OnSerializing() { - if (entity.Content == null) - return; - - // Copy Content.DefaultValue to "content" - if (entity.Content.DefaultValue != null) - outputJson["content"] = JsonValue.Create(entity.Content.DefaultValue, meta.JsonNodeOptions); - - // Remove "contentMap" if it's empty - if (!entity.Content.LanguageMap.Any()) - outputJson.Remove("contentMap"); + Content = ContentMap?.DefaultValue; + + if (ContentMap?.HasLanguages == false) + ContentMap = null; } } \ No newline at end of file diff --git a/Source/ActivityPub.Types/AS/ASType.cs b/Source/ActivityPub.Types/AS/ASType.cs index c204a43..6bd0cad 100644 --- a/Source/ActivityPub.Types/AS/ASType.cs +++ b/Source/ActivityPub.Types/AS/ASType.cs @@ -2,6 +2,7 @@ // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using ActivityPub.Types.Util; using JetBrains.Annotations; @@ -27,7 +28,7 @@ public class ASType : IASModel public ASType() { TypeMap = new TypeMap(); - Entity = TypeMap.Extend(); + Entity = TypeMap.Extend(); } /// @@ -40,11 +41,11 @@ public ASType() /// If extendGraph is and the entity type already exists in the graph /// If extendGraph is and the entity requires another entity that is missing from the graph /// If extendGraph is and the object is not of type TEntity - /// + /// public ASType(TypeMap typeMap, bool isExtending = true) { TypeMap = typeMap; - Entity = TypeMap.ProjectTo(isExtending); + Entity = TypeMap.ProjectTo(isExtending); } /// @@ -54,7 +55,7 @@ public ASType(TypeMap typeMap, bool isExtending = true) public ASType(TypeMap typeMap, ASTypeEntity? entity) { TypeMap = typeMap; - Entity = entity ?? typeMap.AsEntity(); + Entity = entity ?? typeMap.AsEntity(); } static ASType IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); @@ -131,7 +132,6 @@ public string? MediaType set => Entity.MediaType = value; } - /// public bool Is() where TModel : ASType, IASModel diff --git a/Source/ActivityPub.Types/AS/Collection/ASCollection.cs b/Source/ActivityPub.Types/AS/Collection/ASCollection.cs index 35b4deb..a30ff91 100644 --- a/Source/ActivityPub.Types/AS/Collection/ASCollection.cs +++ b/Source/ActivityPub.Types/AS/Collection/ASCollection.cs @@ -29,11 +29,11 @@ public class ASCollection : ASObject, IASModel.ASTypeName => CollectionType; /// - public ASCollection() => Entity = TypeMap.Extend(); + public ASCollection() => Entity = TypeMap.Extend(); /// public ASCollection(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASCollection(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -41,7 +41,7 @@ public ASCollection(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ASCollection(TypeMap typeMap, ASCollectionEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASCollection IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Collection/ASCollectionPage.cs b/Source/ActivityPub.Types/AS/Collection/ASCollectionPage.cs index c9a6fe1..d24afbe 100644 --- a/Source/ActivityPub.Types/AS/Collection/ASCollectionPage.cs +++ b/Source/ActivityPub.Types/AS/Collection/ASCollectionPage.cs @@ -26,11 +26,11 @@ public class ASCollectionPage : ASCollection, IASModel.ASTypeName => CollectionPageType; /// - public ASCollectionPage() => Entity = TypeMap.Extend(); + public ASCollectionPage() => Entity = TypeMap.Extend(); /// public ASCollectionPage(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASCollectionPage(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -38,7 +38,7 @@ public ASCollectionPage(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ASCollectionPage(TypeMap typeMap, ASCollectionPageEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASCollectionPage IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Collection/ASOrderedCollection.cs b/Source/ActivityPub.Types/AS/Collection/ASOrderedCollection.cs index 7f3fa7f..d07f322 100644 --- a/Source/ActivityPub.Types/AS/Collection/ASOrderedCollection.cs +++ b/Source/ActivityPub.Types/AS/Collection/ASOrderedCollection.cs @@ -29,11 +29,11 @@ public class ASOrderedCollection : ASObject, IASModel.ASTypeName => OrderedCollectionType; /// - public ASOrderedCollection() => Entity = TypeMap.Extend(); + public ASOrderedCollection() => Entity = TypeMap.Extend(); /// public ASOrderedCollection(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASOrderedCollection(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -41,7 +41,7 @@ public ASOrderedCollection(ASType existingGraph) : this(existingGraph.TypeMap) { /// [SetsRequiredMembers] public ASOrderedCollection(TypeMap typeMap, ASOrderedCollectionEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASOrderedCollection IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Collection/ASOrderedCollectionPage.cs b/Source/ActivityPub.Types/AS/Collection/ASOrderedCollectionPage.cs index cf23d17..a4f90e5 100644 --- a/Source/ActivityPub.Types/AS/Collection/ASOrderedCollectionPage.cs +++ b/Source/ActivityPub.Types/AS/Collection/ASOrderedCollectionPage.cs @@ -26,11 +26,11 @@ public class ASOrderedCollectionPage : ASOrderedCollection, IASModel.ASTypeName => OrderedCollectionPageType; /// - public ASOrderedCollectionPage() => Entity = TypeMap.Extend(); + public ASOrderedCollectionPage() => Entity = TypeMap.Extend(); /// public ASOrderedCollectionPage(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ASOrderedCollectionPage(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -38,7 +38,7 @@ public ASOrderedCollectionPage(ASType existingGraph) : this(existingGraph.TypeMa /// [SetsRequiredMembers] public ASOrderedCollectionPage(TypeMap typeMap, ASOrderedCollectionPageEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ASOrderedCollectionPage IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/AcceptActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/AcceptActivity.cs index 6b47f32..570cc81 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/AcceptActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/AcceptActivity.cs @@ -20,11 +20,11 @@ public class AcceptActivity : ASActivity, IASModel.ASTypeName => AcceptType; /// - public AcceptActivity() => Entity = TypeMap.Extend(); + public AcceptActivity() => Entity = TypeMap.Extend(); /// public AcceptActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public AcceptActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public AcceptActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public AcceptActivity(TypeMap typeMap, AcceptActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static AcceptActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/AddActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/AddActivity.cs index 196e512..437be85 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/AddActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/AddActivity.cs @@ -21,11 +21,11 @@ public class AddActivity : ASActivity, IASModel.ASTypeName => AddType; /// - public AddActivity() => Entity = TypeMap.Extend(); + public AddActivity() => Entity = TypeMap.Extend(); /// public AddActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public AddActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public AddActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public AddActivity(TypeMap typeMap, AddActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static AddActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/AnnounceActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/AnnounceActivity.cs index 8fde35b..92ea1b3 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/AnnounceActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/AnnounceActivity.cs @@ -21,11 +21,11 @@ public class AnnounceActivity : ASActivity, IASModel.ASTypeName => AnnounceType; /// - public AnnounceActivity() => Entity = TypeMap.Extend(); + public AnnounceActivity() => Entity = TypeMap.Extend(); /// public AnnounceActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public AnnounceActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public AnnounceActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public AnnounceActivity(TypeMap typeMap, AnnounceActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static AnnounceActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/ArriveActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/ArriveActivity.cs index 402bc85..d27bad5 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/ArriveActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/ArriveActivity.cs @@ -22,11 +22,11 @@ public class ArriveActivity : ASIntransitiveActivity, IASModel.ASTypeName => ArriveType; /// - public ArriveActivity() => Entity = TypeMap.Extend(); + public ArriveActivity() => Entity = TypeMap.Extend(); /// public ArriveActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ArriveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public ArriveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ArriveActivity(TypeMap typeMap, ArriveActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ArriveActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/BlockActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/BlockActivity.cs index be21d85..e7de536 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/BlockActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/BlockActivity.cs @@ -23,11 +23,11 @@ public class BlockActivity : IgnoreActivity, IASModel.ASTypeName => BlockType; /// - public BlockActivity() => Entity = TypeMap.Extend(); + public BlockActivity() => Entity = TypeMap.Extend(); /// public BlockActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public BlockActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -35,7 +35,7 @@ public BlockActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public BlockActivity(TypeMap typeMap, BlockActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static BlockActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/CreateActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/CreateActivity.cs index 50f1b3a..6c40290 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/CreateActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/CreateActivity.cs @@ -20,11 +20,11 @@ public class CreateActivity : ASActivity, IASModel.ASTypeName => CreateType; /// - public CreateActivity() => Entity = TypeMap.Extend(); + public CreateActivity() => Entity = TypeMap.Extend(); /// public CreateActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public CreateActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public CreateActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public CreateActivity(TypeMap typeMap, CreateActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static CreateActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/DeleteActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/DeleteActivity.cs index 335abd3..dd0401f 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/DeleteActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/DeleteActivity.cs @@ -21,11 +21,11 @@ public class DeleteActivity : ASActivity, IASModel.ASTypeName => DeleteType; /// - public DeleteActivity() => Entity = TypeMap.Extend(); + public DeleteActivity() => Entity = TypeMap.Extend(); /// public DeleteActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public DeleteActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public DeleteActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public DeleteActivity(TypeMap typeMap, DeleteActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static DeleteActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/DislikeActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/DislikeActivity.cs index f520f50..0939303 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/DislikeActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/DislikeActivity.cs @@ -20,11 +20,11 @@ public class DislikeActivity : ASActivity, IASModel.ASTypeName => DislikeType; /// - public DislikeActivity() => Entity = TypeMap.Extend(); + public DislikeActivity() => Entity = TypeMap.Extend(); /// public DislikeActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public DislikeActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public DislikeActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public DislikeActivity(TypeMap typeMap, DislikeActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static DislikeActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/FlagActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/FlagActivity.cs index d04daf8..0dc0464 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/FlagActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/FlagActivity.cs @@ -21,11 +21,11 @@ public class FlagActivity : ASActivity, IASModel.ASTypeName => FlagType; /// - public FlagActivity() => Entity = TypeMap.Extend(); + public FlagActivity() => Entity = TypeMap.Extend(); /// public FlagActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public FlagActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public FlagActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public FlagActivity(TypeMap typeMap, FlagActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static FlagActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/FollowActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/FollowActivity.cs index fe27314..0d5bdfe 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/FollowActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/FollowActivity.cs @@ -22,11 +22,11 @@ public class FollowActivity : ASActivity, IASModel.ASTypeName => FollowType; /// - public FollowActivity() => Entity = TypeMap.Extend(); + public FollowActivity() => Entity = TypeMap.Extend(); /// public FollowActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public FollowActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public FollowActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public FollowActivity(TypeMap typeMap, FollowActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static FollowActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/IgnoreActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/IgnoreActivity.cs index eaab7ce..cf31d61 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/IgnoreActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/IgnoreActivity.cs @@ -20,11 +20,11 @@ public class IgnoreActivity : ASActivity, IASModel.ASTypeName => IgnoreType; /// - public IgnoreActivity() => Entity = TypeMap.Extend(); + public IgnoreActivity() => Entity = TypeMap.Extend(); /// public IgnoreActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public IgnoreActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public IgnoreActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public IgnoreActivity(TypeMap typeMap, IgnoreActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static IgnoreActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/InviteActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/InviteActivity.cs index 1c9e926..618d519 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/InviteActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/InviteActivity.cs @@ -20,11 +20,11 @@ public class InviteActivity : OfferActivity, IASModel.ASTypeName => InviteType; /// - public InviteActivity() => Entity = TypeMap.Extend(); + public InviteActivity() => Entity = TypeMap.Extend(); /// public InviteActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public InviteActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public InviteActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public InviteActivity(TypeMap typeMap, InviteActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static InviteActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/JoinActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/JoinActivity.cs index efec58e..84fa9e8 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/JoinActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/JoinActivity.cs @@ -21,11 +21,11 @@ public class JoinActivity : ASActivity, IASModel.ASTypeName => JoinType; /// - public JoinActivity() => Entity = TypeMap.Extend(); + public JoinActivity() => Entity = TypeMap.Extend(); /// public JoinActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public JoinActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public JoinActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public JoinActivity(TypeMap typeMap, JoinActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static JoinActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/LeaveActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/LeaveActivity.cs index e2759b5..3d4d51f 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/LeaveActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/LeaveActivity.cs @@ -21,11 +21,11 @@ public class LeaveActivity : ASActivity, IASModel.ASTypeName => LeaveType; /// - public LeaveActivity() => Entity = TypeMap.Extend(); + public LeaveActivity() => Entity = TypeMap.Extend(); /// public LeaveActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public LeaveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public LeaveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public LeaveActivity(TypeMap typeMap, LeaveActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static LeaveActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/LikeActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/LikeActivity.cs index bcfdebb..8336886 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/LikeActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/LikeActivity.cs @@ -21,11 +21,11 @@ public class LikeActivity : ASActivity, IASModel.ASTypeName => LikeType; /// - public LikeActivity() => Entity = TypeMap.Extend(); + public LikeActivity() => Entity = TypeMap.Extend(); /// public LikeActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public LikeActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public LikeActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public LikeActivity(TypeMap typeMap, LikeActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static LikeActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/ListenActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/ListenActivity.cs index 750c59c..58ca893 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/ListenActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/ListenActivity.cs @@ -20,11 +20,11 @@ public class ListenActivity : ASActivity, IASModel.ASTypeName => ListenType; /// - public ListenActivity() => Entity = TypeMap.Extend(); + public ListenActivity() => Entity = TypeMap.Extend(); /// public ListenActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ListenActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ListenActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ListenActivity(TypeMap typeMap, ListenActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ListenActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/MoveActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/MoveActivity.cs index 4e3eaeb..9a710ee 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/MoveActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/MoveActivity.cs @@ -21,11 +21,11 @@ public class MoveActivity : ASActivity, IASModel.ASTypeName => MoveType; /// - public MoveActivity() => Entity = TypeMap.Extend(); + public MoveActivity() => Entity = TypeMap.Extend(); /// public MoveActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public MoveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public MoveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public MoveActivity(TypeMap typeMap, MoveActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static MoveActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/OfferActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/OfferActivity.cs index efdf860..49f76bb 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/OfferActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/OfferActivity.cs @@ -21,11 +21,11 @@ public class OfferActivity : ASActivity, IASModel.ASTypeName => OfferType; /// - public OfferActivity() => Entity = TypeMap.Extend(); + public OfferActivity() => Entity = TypeMap.Extend(); /// public OfferActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public OfferActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public OfferActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public OfferActivity(TypeMap typeMap, OfferActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static OfferActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/QuestionActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/QuestionActivity.cs index 13bc656..68af93e 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/QuestionActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/QuestionActivity.cs @@ -24,11 +24,11 @@ public class QuestionActivity : ASIntransitiveActivity, IASModel.ASTypeName => QuestionType; /// - public QuestionActivity() => Entity = TypeMap.Extend(); + public QuestionActivity() => Entity = TypeMap.Extend(); /// public QuestionActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public QuestionActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -36,7 +36,7 @@ public QuestionActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public QuestionActivity(TypeMap typeMap, QuestionActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static QuestionActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/ReadActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/ReadActivity.cs index 33a2ce7..eec891a 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/ReadActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/ReadActivity.cs @@ -20,11 +20,11 @@ public class ReadActivity : ASActivity, IASModel.ASTypeName => ReadType; /// - public ReadActivity() => Entity = TypeMap.Extend(); + public ReadActivity() => Entity = TypeMap.Extend(); /// public ReadActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ReadActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ReadActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ReadActivity(TypeMap typeMap, ReadActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ReadActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/RejectActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/RejectActivity.cs index 5245e7f..73eab0b 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/RejectActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/RejectActivity.cs @@ -21,11 +21,11 @@ public class RejectActivity : ASActivity, IASModel.ASTypeName => RejectType; /// - public RejectActivity() => Entity = TypeMap.Extend(); + public RejectActivity() => Entity = TypeMap.Extend(); /// public RejectActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public RejectActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public RejectActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public RejectActivity(TypeMap typeMap, RejectActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static RejectActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/RemoveActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/RemoveActivity.cs index 734b3e8..ad953ae 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/RemoveActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/RemoveActivity.cs @@ -21,11 +21,11 @@ public class RemoveActivity : ASActivity, IASModel.ASTypeName => RemoveType; /// - public RemoveActivity() => Entity = TypeMap.Extend(); + public RemoveActivity() => Entity = TypeMap.Extend(); /// public RemoveActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public RemoveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public RemoveActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public RemoveActivity(TypeMap typeMap, RemoveActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static RemoveActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/TentativeAcceptActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/TentativeAcceptActivity.cs index 2949fcf..8f198b0 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/TentativeAcceptActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/TentativeAcceptActivity.cs @@ -20,11 +20,11 @@ public class TentativeAcceptActivity : AcceptActivity, IASModel.ASTypeName => TentativeAcceptType; /// - public TentativeAcceptActivity() => Entity = TypeMap.Extend(); + public TentativeAcceptActivity() => Entity = TypeMap.Extend(); /// public TentativeAcceptActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public TentativeAcceptActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public TentativeAcceptActivity(ASType existingGraph) : this(existingGraph.TypeMa /// [SetsRequiredMembers] public TentativeAcceptActivity(TypeMap typeMap, TentativeAcceptActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static TentativeAcceptActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/TentativeRejectActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/TentativeRejectActivity.cs index b7ceba3..7275982 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/TentativeRejectActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/TentativeRejectActivity.cs @@ -20,11 +20,11 @@ public class TentativeRejectActivity : RejectActivity, IASModel.ASTypeName => TentativeRejectType; /// - public TentativeRejectActivity() => Entity = TypeMap.Extend(); + public TentativeRejectActivity() => Entity = TypeMap.Extend(); /// public TentativeRejectActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public TentativeRejectActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public TentativeRejectActivity(ASType existingGraph) : this(existingGraph.TypeMa /// [SetsRequiredMembers] public TentativeRejectActivity(TypeMap typeMap, TentativeRejectActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static TentativeRejectActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/TravelActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/TravelActivity.cs index ffbf294..45c4717 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/TravelActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/TravelActivity.cs @@ -22,11 +22,11 @@ public class TravelActivity : ASIntransitiveActivity, IASModel.ASTypeName => TravelType; /// - public TravelActivity() => Entity = TypeMap.Extend(); + public TravelActivity() => Entity = TypeMap.Extend(); /// public TravelActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public TravelActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public TravelActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public TravelActivity(TypeMap typeMap, TravelActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static TravelActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/UndoActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/UndoActivity.cs index b3ec48d..8414b29 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/UndoActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/UndoActivity.cs @@ -22,11 +22,11 @@ public class UndoActivity : ASActivity, IASModel.ASTypeName => UndoType; /// - public UndoActivity() => Entity = TypeMap.Extend(); + public UndoActivity() => Entity = TypeMap.Extend(); /// public UndoActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public UndoActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public UndoActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public UndoActivity(TypeMap typeMap, UndoActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static UndoActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/UpdateActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/UpdateActivity.cs index f379983..7a889c4 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/UpdateActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/UpdateActivity.cs @@ -22,11 +22,11 @@ public class UpdateActivity : ASActivity, IASModel.ASTypeName => UpdateType; /// - public UpdateActivity() => Entity = TypeMap.Extend(); + public UpdateActivity() => Entity = TypeMap.Extend(); /// public UpdateActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public UpdateActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public UpdateActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public UpdateActivity(TypeMap typeMap, UpdateActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static UpdateActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Activity/ViewActivity.cs b/Source/ActivityPub.Types/AS/Extended/Activity/ViewActivity.cs index fe5f97f..71edb00 100644 --- a/Source/ActivityPub.Types/AS/Extended/Activity/ViewActivity.cs +++ b/Source/ActivityPub.Types/AS/Extended/Activity/ViewActivity.cs @@ -20,11 +20,11 @@ public class ViewActivity : ASActivity, IASModel.ASTypeName => ViewType; /// - public ViewActivity() => Entity = TypeMap.Extend(); + public ViewActivity() => Entity = TypeMap.Extend(); /// public ViewActivity(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ViewActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ViewActivity(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ViewActivity(TypeMap typeMap, ViewActivityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ViewActivity IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Actor/ApplicationActor.cs b/Source/ActivityPub.Types/AS/Extended/Actor/ApplicationActor.cs index 50c5806..73c627c 100644 --- a/Source/ActivityPub.Types/AS/Extended/Actor/ApplicationActor.cs +++ b/Source/ActivityPub.Types/AS/Extended/Actor/ApplicationActor.cs @@ -20,11 +20,11 @@ public class ApplicationActor : APActor, IASModel.ASTypeName => ApplicationType; /// - public ApplicationActor() => Entity = TypeMap.Extend(); + public ApplicationActor() => Entity = TypeMap.Extend(); /// public ApplicationActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ApplicationActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ApplicationActor(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ApplicationActor(TypeMap typeMap, ApplicationActorEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ApplicationActor IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Actor/GroupActor.cs b/Source/ActivityPub.Types/AS/Extended/Actor/GroupActor.cs index 54b9a48..c8f540d 100644 --- a/Source/ActivityPub.Types/AS/Extended/Actor/GroupActor.cs +++ b/Source/ActivityPub.Types/AS/Extended/Actor/GroupActor.cs @@ -20,11 +20,11 @@ public class GroupActor : APActor, IASModel.ASTypeName => GroupType; /// - public GroupActor() => Entity = TypeMap.Extend(); + public GroupActor() => Entity = TypeMap.Extend(); /// public GroupActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public GroupActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public GroupActor(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public GroupActor(TypeMap typeMap, GroupActorEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static GroupActor IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Actor/OrganizationActor.cs b/Source/ActivityPub.Types/AS/Extended/Actor/OrganizationActor.cs index 3c68801..9a4ecf1 100644 --- a/Source/ActivityPub.Types/AS/Extended/Actor/OrganizationActor.cs +++ b/Source/ActivityPub.Types/AS/Extended/Actor/OrganizationActor.cs @@ -20,11 +20,11 @@ public class OrganizationActor : APActor, IASModel.ASTypeName => OrganizationType; /// - public OrganizationActor() => Entity = TypeMap.Extend(); + public OrganizationActor() => Entity = TypeMap.Extend(); /// public OrganizationActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public OrganizationActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public OrganizationActor(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public OrganizationActor(TypeMap typeMap, OrganizationActorEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static OrganizationActor IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Actor/PersonActor.cs b/Source/ActivityPub.Types/AS/Extended/Actor/PersonActor.cs index d6a424f..d1dd982 100644 --- a/Source/ActivityPub.Types/AS/Extended/Actor/PersonActor.cs +++ b/Source/ActivityPub.Types/AS/Extended/Actor/PersonActor.cs @@ -20,11 +20,11 @@ public class PersonActor : APActor, IASModel.ASTypeName => PersonType; /// - public PersonActor() => Entity = TypeMap.Extend(); + public PersonActor() => Entity = TypeMap.Extend(); /// public PersonActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public PersonActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public PersonActor(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public PersonActor(TypeMap typeMap, PersonActorEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static PersonActor IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Actor/ServiceActor.cs b/Source/ActivityPub.Types/AS/Extended/Actor/ServiceActor.cs index 0055ef5..b9b2382 100644 --- a/Source/ActivityPub.Types/AS/Extended/Actor/ServiceActor.cs +++ b/Source/ActivityPub.Types/AS/Extended/Actor/ServiceActor.cs @@ -20,11 +20,11 @@ public class ServiceActor : APActor, IASModel.ASTypeName => ServiceType; /// - public ServiceActor() => Entity = TypeMap.Extend(); + public ServiceActor() => Entity = TypeMap.Extend(); /// public ServiceActor(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ServiceActor(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ServiceActor(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ServiceActor(TypeMap typeMap, ServiceActorEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ServiceActor IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Link/MentionLink.cs b/Source/ActivityPub.Types/AS/Extended/Link/MentionLink.cs index e53e6b1..83c49b1 100644 --- a/Source/ActivityPub.Types/AS/Extended/Link/MentionLink.cs +++ b/Source/ActivityPub.Types/AS/Extended/Link/MentionLink.cs @@ -20,11 +20,11 @@ public class MentionLink : ASLink, IASModel.ASTypeName => MentionType; /// - public MentionLink() => Entity = TypeMap.Extend(); + public MentionLink() => Entity = TypeMap.Extend(); /// public MentionLink(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public MentionLink(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public MentionLink(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public MentionLink(TypeMap typeMap, MentionLinkEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static MentionLink IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/ArticleObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/ArticleObject.cs index d1f598d..7ce5730 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/ArticleObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/ArticleObject.cs @@ -20,11 +20,11 @@ public class ArticleObject : ASObject, IASModel.ASTypeName => ArticleType; /// - public ArticleObject() => Entity = TypeMap.Extend(); + public ArticleObject() => Entity = TypeMap.Extend(); /// public ArticleObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ArticleObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ArticleObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ArticleObject(TypeMap typeMap, ArticleObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ArticleObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/AudioObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/AudioObject.cs index f6a1a27..2945fdf 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/AudioObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/AudioObject.cs @@ -20,11 +20,11 @@ public class AudioObject : DocumentObject, IASModel.ASTypeName => AudioType; /// - public AudioObject() => Entity = TypeMap.Extend(); + public AudioObject() => Entity = TypeMap.Extend(); /// public AudioObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public AudioObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public AudioObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public AudioObject(TypeMap typeMap, AudioObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static AudioObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/DocumentObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/DocumentObject.cs index 315467b..7761abc 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/DocumentObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/DocumentObject.cs @@ -20,11 +20,11 @@ public class DocumentObject : ASObject, IASModel.ASTypeName => DocumentType; /// - public DocumentObject() => Entity = TypeMap.Extend(); + public DocumentObject() => Entity = TypeMap.Extend(); /// public DocumentObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public DocumentObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public DocumentObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public DocumentObject(TypeMap typeMap, DocumentObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static DocumentObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/EventObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/EventObject.cs index 0477c85..bddb681 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/EventObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/EventObject.cs @@ -20,11 +20,11 @@ public class EventObject : ASObject, IASModel.ASTypeName => EventType; /// - public EventObject() => Entity = TypeMap.Extend(); + public EventObject() => Entity = TypeMap.Extend(); /// public EventObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public EventObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public EventObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public EventObject(TypeMap typeMap, EventObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static EventObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/ImageObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/ImageObject.cs index 9639dde..caa1e41 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/ImageObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/ImageObject.cs @@ -20,11 +20,11 @@ public class ImageObject : DocumentObject, IASModel.ASTypeName => ImageType; /// - public ImageObject() => Entity = TypeMap.Extend(); + public ImageObject() => Entity = TypeMap.Extend(); /// public ImageObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ImageObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public ImageObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ImageObject(TypeMap typeMap, ImageObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ImageObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/NoteObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/NoteObject.cs index 00f9ce3..99d0d83 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/NoteObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/NoteObject.cs @@ -20,11 +20,11 @@ public class NoteObject : ASObject, IASModel.ASTypeName => NoteType; /// - public NoteObject() => Entity = TypeMap.Extend(); + public NoteObject() => Entity = TypeMap.Extend(); /// public NoteObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public NoteObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public NoteObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public NoteObject(TypeMap typeMap, NoteObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static NoteObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/PageObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/PageObject.cs index c3e1101..fc39f47 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/PageObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/PageObject.cs @@ -20,11 +20,11 @@ public class PageObject : DocumentObject, IASModel.ASTypeName => PageType; /// - public PageObject() => Entity = TypeMap.Extend(); + public PageObject() => Entity = TypeMap.Extend(); /// public PageObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public PageObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public PageObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public PageObject(TypeMap typeMap, PageObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static PageObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/PlaceObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/PlaceObject.cs index a10166a..d97fe57 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/PlaceObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/PlaceObject.cs @@ -20,11 +20,11 @@ public class PlaceObject : ASObject, IASModel.ASTypeName => PlaceType; /// - public PlaceObject() => Entity = TypeMap.Extend(); + public PlaceObject() => Entity = TypeMap.Extend(); /// public PlaceObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public PlaceObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public PlaceObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public PlaceObject(TypeMap typeMap, PlaceObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static PlaceObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/ProfileObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/ProfileObject.cs index ff10f53..035cefa 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/ProfileObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/ProfileObject.cs @@ -21,11 +21,11 @@ public class ProfileObject : ASObject, IASModel.ASTypeName => ProfileType; /// - public ProfileObject() => Entity = TypeMap.Extend(); + public ProfileObject() => Entity = TypeMap.Extend(); /// public ProfileObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public ProfileObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public ProfileObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public ProfileObject(TypeMap typeMap, ProfileObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static ProfileObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/RelationshipObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/RelationshipObject.cs index 16a4583..3749e4d 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/RelationshipObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/RelationshipObject.cs @@ -22,11 +22,11 @@ public class RelationshipObject : ASObject, IASModel.ASTypeName => RelationshipType; /// - public RelationshipObject() => Entity = TypeMap.Extend(); + public RelationshipObject() => Entity = TypeMap.Extend(); /// public RelationshipObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public RelationshipObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -34,7 +34,7 @@ public RelationshipObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public RelationshipObject(TypeMap typeMap, RelationshipObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static RelationshipObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/TombstoneObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/TombstoneObject.cs index f746b40..4c6cca0 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/TombstoneObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/TombstoneObject.cs @@ -21,11 +21,11 @@ public class TombstoneObject : ASObject, IASModel.ASTypeName => TombstoneType; /// - public TombstoneObject() => Entity = TypeMap.Extend(); + public TombstoneObject() => Entity = TypeMap.Extend(); /// public TombstoneObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public TombstoneObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -33,7 +33,7 @@ public TombstoneObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public TombstoneObject(TypeMap typeMap, TombstoneObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static TombstoneObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/AS/Extended/Object/VideoObject.cs b/Source/ActivityPub.Types/AS/Extended/Object/VideoObject.cs index 3654eaa..332d46c 100644 --- a/Source/ActivityPub.Types/AS/Extended/Object/VideoObject.cs +++ b/Source/ActivityPub.Types/AS/Extended/Object/VideoObject.cs @@ -20,11 +20,11 @@ public class VideoObject : DocumentObject, IASModel.ASTypeName => VideoType; /// - public VideoObject() => Entity = TypeMap.Extend(); + public VideoObject() => Entity = TypeMap.Extend(); /// public VideoObject(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public VideoObject(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -32,7 +32,7 @@ public VideoObject(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public VideoObject(TypeMap typeMap, VideoObjectEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static VideoObject IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Source/ActivityPub.Types/Conversion/ASTypeInfoCache.cs b/Source/ActivityPub.Types/Conversion/ASTypeInfoCache.cs deleted file mode 100644 index a9c9bc9..0000000 --- a/Source/ActivityPub.Types/Conversion/ASTypeInfoCache.cs +++ /dev/null @@ -1,257 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using ActivityPub.Types.AS; -using ActivityPub.Types.Conversion.Overrides; -using ActivityPub.Types.Internal; - -namespace ActivityPub.Types.Conversion; - -/// -/// Extracts and stores metadata for ActivityStreams types within the application. -/// -[Obsolete("ASTypeInfoCache will be removed in a future update")] -public interface IASTypeInfoCache -{ - /// - /// Finds the .NET type(s) that implement a set of AS types. - /// Implied types are automatically included. - /// Unknown types are safely ignored. - /// - /// Types to map. Case-sensitive. - /// All known entities that represent the types. - /// Any AS types that did not map to an entity. - /// Set of all located types - public void MapASTypesToEntities(IEnumerable asTypes, out HashSet mappedEntities, out HashSet unmappedTypes); - - /// - /// Gets the .NET type that implements a specified AS type. - /// Returns true on success or false on failure, following the TryGet pattern. - /// - public bool TryGetModelType(string asType, [NotNullWhen(true)] out Type? modelType); - - /// - /// All known types that implement . - /// - public IEnumerable AnonymousEntityTypes { get; } - - /// - /// All known types that implement . - /// - public IEnumerable NamelessEntityTypes { get; } - - /// - /// Find and load all ActivityStreams types in a particular assembly. - /// - /// Assembly to load - public void RegisterAssembly(Assembly assembly); - - /// - /// Find and load all ActivityStreams types in all loaded assemblies. - /// - public void RegisterAllAssemblies(); -} - -/// -/// Default implementation of . -/// At startup, uses reflection to index all loaded types. -/// -[Obsolete("ASTypeInfoCache will be removed in a future update")] -public class ASTypeInfoCache : IASTypeInfoCache -{ - private static readonly Lazy Lazy = new(() => - { - var cache = new ASTypeInfoCache(); - cache.RegisterAllAssemblies(); - return cache; - }); - private readonly HashSet _registeredAssemblies = new(); - - private readonly Dictionary _typeMetaMap = new(); - private readonly Dictionary _nameMetaMap = new(); - - /// - public IEnumerable AnonymousEntityTypes => _anonymousEntityTypes; - private readonly HashSet _anonymousEntityTypes = new(); - - /// - public IEnumerable NamelessEntityTypes => _namelessEntityTypes; - - /// - /// A global static instance of ASTypeInfoCache - /// - public static ASTypeInfoCache Instance => Lazy.Value; - private readonly HashSet _namelessEntityTypes = new(); - - /// - /// Calls with a specified value for TModel. - /// - private readonly Func _createTypeMetadataFor; - - internal ASTypeInfoCache() => - // I really hate doing this :sob: - _createTypeMetadataFor = typeof(ASTypeInfoCache) - .GetRequiredMethod(nameof(CreateModelMetaFor), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotFunc(this); - - /// - public void MapASTypesToEntities(IEnumerable asTypes, out HashSet mappedEntities, out HashSet unmappedTypes) - { - mappedEntities = new HashSet(); - unmappedTypes = new HashSet(); - - foreach (var asType in asTypes) - { - // Map AS Type to .NET Type. - if (_nameMetaMap.TryGetValue(asType, out var meta)) - mappedEntities.AddRange(meta.EntityTypeChain); - - // Record unknown types too - else - unmappedTypes.Add(asType); - } - } - - /// - public bool TryGetModelType(string asType, [NotNullWhen(true)] out Type? modelType) - { - if (_nameMetaMap.TryGetValue(asType, out var meta)) - { - modelType = meta.ModelType; - return true; - } - - modelType = null; - return false; - } - - /// - public void RegisterAllAssemblies() - { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) - RegisterAssembly(assembly); - } - - /// - public void RegisterAssembly(Assembly assembly) - { - // Make sure we only check each assembly once. - // Its an extremely heavy operation. - if (!_registeredAssemblies.Add(assembly)) - return; - - // This is a new assembly, so we need to check every type - foreach (var type in assembly.GetTypes()) - RegisterType(type); - } - - private void RegisterType(Type type) - { - // Skip if we've already check it - if (_typeMetaMap.ContainsKey(type)) - return; - - // Skip if it's not an AS type - if (!type.IsAssignableTo(typeof(ASType))) - // Also register IAnonymousEntitySelectors? - // Now that I look at it, I'm not sure it makes sense for those to come from IOptions, anyway - return; - - // Skip if it's not a model - if (!typeof(IASModel<>).TryMakeGenericType(out var modelType, type)) - return; - if (!type.IsAssignableTo(modelType)) - return; - - // Make sure that base types are populated first - if (type.BaseType != null) - RegisterType(type.BaseType); - - var meta = _createTypeMetadataFor(type); - _typeMetaMap[type] = meta; - - // Register named entities - var asTypeName = meta.ASTypeName; - if (asTypeName != null) - { - // Check for duplicates! - if (_nameMetaMap.TryGetValue(asTypeName, out var conflictMeta)) - throw new ApplicationException($"Multiple classes are using AS type name {asTypeName}: trying to register {type} on top of {conflictMeta.ModelType}"); - - _nameMetaMap[asTypeName] = meta; - } - - // Register anonymous entities - var entityType = meta.EntityType; - if (entityType.IsAssignableTo(typeof(IAnonymousEntity))) - _anonymousEntityTypes.Add(entityType); - - // Register nameless entities - if (entityType.IsAssignableTo(typeof(INamelessEntity))) - _namelessEntityTypes.Add(entityType); - } - - private ModelMeta CreateModelMetaFor() - where TModel : ASType, IASModel - { - var modelType = typeof(TModel); - - return new ModelMeta - { - ModelType = modelType, - EntityTypeChain = GetEntityTypeChain(modelType), - EntityType = TModel.EntityType, - ASTypeName = TModel.ASTypeName - }; - } - - private List GetEntityTypeChain(Type modelType) - where TModel : ASType, IASModel - { - var entityTypes = new List - { - TModel.EntityType - }; - - for (var baseType = modelType.BaseType; baseType != null; baseType = baseType.BaseType) - { - // Some base types may not be models. - // If this happens, we need to skip but NOT bail out! - if (!_typeMetaMap.TryGetValue(baseType, out var baseMeta)) - continue; - - entityTypes.Add(baseMeta.EntityType); - } - - return entityTypes; - } - - /// - /// Cached metadata about an AS Model. - /// - private class ModelMeta - { - /// - /// Type of the model class - /// - public required Type ModelType { get; init; } - - /// - /// Type of the entity class, taken from . - /// - public required Type EntityType { get; init; } - - /// - /// List of all entities required to represent the data used by this model. - /// Effectively, it is along with the entity type of every ancestor model. - /// - public required IReadOnlyList EntityTypeChain { get; init; } - - /// - /// The model's AS type name, taken from . - /// - public string? ASTypeName { get; init; } - } -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Converters/LinkableConverter.cs b/Source/ActivityPub.Types/Conversion/Converters/LinkableConverter.cs index fcdd05b..ad17c58 100644 --- a/Source/ActivityPub.Types/Conversion/Converters/LinkableConverter.cs +++ b/Source/ActivityPub.Types/Conversion/Converters/LinkableConverter.cs @@ -1,12 +1,9 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. -using System.Diagnostics.CodeAnalysis; -using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; using ActivityPub.Types.AS; -using ActivityPub.Types.Internal; using ActivityPub.Types.Util; namespace ActivityPub.Types.Conversion.Converters; @@ -16,11 +13,6 @@ namespace ActivityPub.Types.Conversion.Converters; /// public class LinkableConverter : JsonConverterFactory { - private readonly IASTypeInfoCache _asTypeInfoCache; - - /// - public LinkableConverter(IASTypeInfoCache asTypeInfoCache) => _asTypeInfoCache = asTypeInfoCache; - /// public override bool CanConvert(Type type) => // We only convert Linkable @@ -33,21 +25,13 @@ public override JsonConverter CreateConverter(Type type, JsonSerializerOptions o var converterType = typeof(LinkableConverter<>).MakeGenericType(valueType); // Pivot the type into correct instance - return (JsonConverter)Activator.CreateInstance( - converterType, - BindingFlags.Instance | BindingFlags.Public, - null, - new object[] { _asTypeInfoCache }, - null - )!; + return (JsonConverter)Activator.CreateInstance(converterType)!; } } internal class LinkableConverter : JsonConverter> + where T : ASType, IASModel { - private readonly IASTypeInfoCache _asTypeInfoCache; - public LinkableConverter(IASTypeInfoCache asTypeInfoCache) => _asTypeInfoCache = asTypeInfoCache; - public override Linkable? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) @@ -55,30 +39,18 @@ internal class LinkableConverter : JsonConverter> // Parse into abstract form var jsonElement = JsonElement.ParseValue(ref reader); + var typeMap = jsonElement.Deserialize(options) + ?? throw new JsonException($"Failed to parse {typeToConvert} - deserialize returned null"); // If it's a string, then it's a link - if (jsonElement.ValueKind == JsonValueKind.String) - { - var link = jsonElement.Deserialize(options); - if (link == null) - throw new JsonException($"Failed to parse {typeToConvert} - Could not construct link object of type {typeof(ASLink)}"); + if (typeMap.IsModel(out var link)) return new Linkable(link); - } - - // If it's an object of type ASLink, then it's still a link - if (TryGetLinkType(jsonElement, out var linkType)) - { - var link = (ASLink?)jsonElement.Deserialize(linkType, options); - if (link == null) - throw new JsonException($"Failed to parse {typeToConvert} - Could not construct link object of type {linkType}"); - return new Linkable(link); - } // Anything else is the payload data - var obj = jsonElement.Deserialize(options); - if (obj == null) - throw new JsonException($"Failed to parse {typeToConvert} - Could not construct value object"); - return new Linkable(obj); + if (typeMap.IsModel(out var obj)) + return new Linkable(obj); + + throw new JsonException($"Failed to parse {typeToConvert} - input cannot be projected to that type"); } public override void Write(Utf8JsonWriter writer, Linkable linkable, JsonSerializerOptions options) @@ -92,20 +64,4 @@ public override void Write(Utf8JsonWriter writer, Linkable linkable, JsonSeri else throw new ArgumentException($"{typeof(Linkable)} is invalid - it has neither a link nor a value"); } - - private bool TryGetLinkType(JsonElement element, [NotNullWhen(true)] out Type? linkType) - { - linkType = null; - - // Firstly, it must have a decodable AS type name - if (!element.TryGetASType(out var asType)) - return false; - - // Second, that name must map to a known model type - if (!_asTypeInfoCache.TryGetModelType(asType, out linkType)) - return false; - - // Finally, the model must be a link - return linkType.IsAssignableTo(typeof(ASLink)); - } } \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Converters/TypeMapConverter.cs b/Source/ActivityPub.Types/Conversion/Converters/TypeMapConverter.cs index 855cad9..f54534b 100644 --- a/Source/ActivityPub.Types/Conversion/Converters/TypeMapConverter.cs +++ b/Source/ActivityPub.Types/Conversion/Converters/TypeMapConverter.cs @@ -7,186 +7,55 @@ using ActivityPub.Types.AS; using ActivityPub.Types.Conversion.Overrides; using ActivityPub.Types.Internal; -using ActivityPub.Types.Internal.Pivots; using ActivityPub.Types.Util; -using JetBrains.Annotations; -using Microsoft.Extensions.Options; namespace ActivityPub.Types.Conversion.Converters; /// public class TypeMapConverter : JsonConverter { - private readonly IASTypeInfoCache _asTypeInfoCache; - private readonly IConversionOptions _conversionOptions; - private readonly NamelessEntityPivot _namelessEntityPivot = new(); - private readonly AnonymousEntityPivot _anonymousEntityPivot = new(); - private readonly CustomConvertedEntityPivot _customConvertedEntityPivot = new(); - - /// - [UsedImplicitly] - public TypeMapConverter(IASTypeInfoCache asTypeInfoCache, IOptions conversionOptions) - { - _asTypeInfoCache = asTypeInfoCache; - _conversionOptions = conversionOptions.Value; - } - - /// - public TypeMapConverter() - { - _asTypeInfoCache = ASTypeInfoCache.Instance; - _conversionOptions = new ConversionOptions(); - } - /// public override TypeMap Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // Read input into temporary object var jsonElement = JsonElement.ParseValue(ref reader); - // Read JSON-LD context from the input JSON - var context = ReadContext(jsonElement, options); - - // Construct empty TypeMap. - // We will build this out progressively. - var typeMap = new TypeMap(context); - - // Construct context for this conversion cycle - var meta = new DeserializationMetadata - { - JsonSerializerOptions = options, - LDContext = context, - TypeMap = typeMap - }; - - ReadKnownEntities(jsonElement, meta); - ReadNamelessEntities(jsonElement, meta); - ReadAnonymousEntities(jsonElement, meta); - - return typeMap; - } - - private void ReadKnownEntities(JsonElement jsonElement, DeserializationMetadata meta) - { // String input is a special case of Link if (jsonElement.ValueKind == JsonValueKind.String) - ReadString(jsonElement, meta.TypeMap); + return ReadString(jsonElement); // Object input can be anything - else if (jsonElement.ValueKind == JsonValueKind.Object) - ReadObject(jsonElement, meta); + if (jsonElement.ValueKind == JsonValueKind.Object) + return ReadObject(jsonElement, options); - // Other input is an error - else - throw new JsonException($"Can't convert TypeMap from {jsonElement.ValueKind}"); + // Any other input is an error + throw new JsonException($"Can't convert TypeMap from {jsonElement.ValueKind}"); } - private static void ReadString(JsonElement jsonElement, TypeMap typeMap) + + private static TypeMap ReadString(JsonElement jsonElement) { // Read Link entity var link = new ASLinkEntity { HRef = jsonElement.GetString()! }; - typeMap.AddEntity(link); - - // Create and attach empty Type entity - var type = new ASTypeEntity(); - typeMap.AddEntity(type); - } - - private void ReadObject(JsonElement jsonElement, DeserializationMetadata meta) - { - // Enumerate and expand the full list of needed types - var asTypes = ReadTypes(jsonElement, meta.JsonSerializerOptions); - _asTypeInfoCache.MapASTypesToEntities(asTypes, out var mappedTypes, out var unmappedTypes); - - // Convert each AS type that mapped to an object type - foreach (var entityType in mappedTypes) - ReadEntity(jsonElement, meta, entityType); - - // Record each AS type that did *not* map to an object type - foreach (var asType in unmappedTypes) - meta.TypeMap.AddUnmappedType(asType); - } - - private void ReadNamelessEntities(JsonElement jsonElement, DeserializationMetadata meta) - { - // Nameless entities must be checked for every input JSON. - // Any that match are converted like normal entities, but skipping the usual AS type lookup. - foreach (var entityType in _asTypeInfoCache.NamelessEntityTypes) - if (_namelessEntityPivot.ShouldConvert(entityType, meta)) - ReadEntity(jsonElement, meta, entityType); - } - - private void ReadAnonymousEntities(JsonElement jsonElement, DeserializationMetadata meta) - { - // Anonymous entities must be checked for every input JSON. - // Any that match are converted like normal entities, but skipping the usual AS type / context lookup. - foreach (var entityType in _asTypeInfoCache.AnonymousEntityTypes) - if (_anonymousEntityPivot.ShouldConvert(entityType, jsonElement, meta)) - ReadEntity(jsonElement, meta, entityType); - - // Registered anonymous entity selectors must also run for every input. - // They can each identify any number of anonymous entities. - foreach (var selector in _conversionOptions.AnonymousEntitySelectors) - foreach (var entityType in selector.SelectAnonymousEntities(jsonElement, meta)) - ReadEntity(jsonElement, meta, entityType); - } - - private void ReadEntity(JsonElement jsonElement, DeserializationMetadata meta, Type entityType) - { - // Skip if the entity is already in the graph - if (meta.TypeMap.AllEntities.ContainsKey(entityType)) - return; - - var entity = - // Use custom logic, if applicable - _customConvertedEntityPivot.ReadEntity(entityType, jsonElement, meta) - - // Fall back to native JSON conversion - ?? (ASEntity?)jsonElement.Deserialize(entityType, meta.JsonSerializerOptions) - // Bail out if both fail - ?? throw new JsonException($"Failed to deserialize {entityType} - JsonElement.Deserialize returned null"); - - // Execute callback, if applicable - _customConvertedEntityPivot.PostReadEntity(entityType, jsonElement, meta, entity); + // Create TypeGraph around it + var context = JsonLDContext.CreateASContext(); + var types = new List { ASLink.LinkType }; + var typeMap = new TypeMap(context, types); - // Add it to the graph. - meta.TypeMap.AddEntity(entity); - - // Remove the entity-level set. - // We need it for conversion, but only until TypeMap is updated - entity.UnmappedProperties = null; - } - - private static IEnumerable ReadTypes(JsonElement jsonElement, JsonSerializerOptions options) - { - HashSet types; - - // Try to read types - if (jsonElement.TryGetProperty("type", out var typeProp)) - types = typeProp.Deserialize>(options) - ?? throw new JsonException("Can't convert TypeMap - \"type\" is null"); - else - types = new HashSet(); - - // Make sure we always have object - types.Add(ASObject.ObjectType); + // Attach entities + typeMap.AddEntity(link); + typeMap.AddEntity(new ASTypeEntity()); - return types; + return typeMap; } - private static JsonLDContext ReadContext(JsonElement jsonElement, JsonSerializerOptions options) + private static TypeMap ReadObject(JsonElement jsonElement, JsonSerializerOptions options) { - // Try to get the context property. - if (jsonElement.ValueKind != JsonValueKind.Object || !jsonElement.TryGetProperty("@context", out var contextProp)) - // If missing then use default. - return JsonLDContext.CreateASContext(); - - // Convert context - return contextProp.Deserialize(options) - ?? throw new JsonException("Can't convert TypeMap - \"@context\" is null"); + var typeGraphReader = new TypeGraphReader(options, jsonElement); + return new TypeMap(typeGraphReader); } /// @@ -222,16 +91,11 @@ public override void Write(Utf8JsonWriter writer, TypeMap typeMap, JsonSerialize outputNode.WriteTo(writer, options); } - private void WriteEntity(ASEntity entity, Type entityType, JsonObject outputNode, SerializationMetadata meta) + private static void WriteEntity(ASEntity entity, Type entityType, JsonObject outputNode, SerializationMetadata meta) { // Convert to an intermediate object. // This will contain the subset of fields that are owned by this entity. - var element = - // Use custom converter, if applicable - _customConvertedEntityPivot.WriteEntity(entityType, entity, meta) - - // Fall back to native conversion - ?? JsonSerializer.SerializeToElement(entity, entityType, meta.JsonSerializerOptions); + var element = JsonSerializer.SerializeToElement(entity, entityType, meta.JsonSerializerOptions); // Sanity check if (element.ValueKind != JsonValueKind.Object) @@ -243,12 +107,9 @@ private void WriteEntity(ASEntity entity, Type entityType, JsonObject outputNode var valueNode = property.Value.ToNode(meta.JsonNodeOptions); outputNode[property.Name] = valueNode; } - - // Execute callback, if applicable - _customConvertedEntityPivot.PostWriteEntity(entityType, entity, meta, element, outputNode); } - private void WriteTypeMap(TypeMap typeMap, JsonObject outputNode, SerializationMetadata meta) + private static void WriteTypeMap(TypeMap typeMap, JsonObject outputNode, SerializationMetadata meta) { // "type" - AS / AP types. Can be string or array. if (typeMap.ASTypes.Count > 0) @@ -275,15 +136,12 @@ private static bool TryWriteAsLink(Utf8JsonWriter writer, TypeMap typeMap) return false; // If there is no ASLinkEntity, then bail - if (!typeMap.IsEntity(out var linkEntity)) + if (!typeMap.IsModel(out var linkModel)) return false; // Finally - its safe to write string form - var href = linkEntity.HRef?.ToString(); - if (href == null) - writer.WriteNullValue(); - else - writer.WriteStringValue(href); + var href = linkModel.HRef.ToString(); + writer.WriteStringValue(href); return true; } } \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Overrides/ConversionOptions.cs b/Source/ActivityPub.Types/Conversion/Overrides/ConversionOptions.cs deleted file mode 100644 index e37ec54..0000000 --- a/Source/ActivityPub.Types/Conversion/Overrides/ConversionOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -namespace ActivityPub.Types.Conversion.Overrides; - - -/// -/// Common options to configure JSON / JSON-LD conversion. -/// -public interface IConversionOptions -{ - /// - /// Additional instances to execute when converting any incoming JSON. - /// - public IEnumerable AnonymousEntitySelectors { get; } -} - -/// -public class ConversionOptions : IConversionOptions -{ - /// - public HashSet AnonymousEntitySelectors { get; set; } = new(); - IEnumerable IConversionOptions.AnonymousEntitySelectors => AnonymousEntitySelectors; -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntity.cs b/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntity.cs deleted file mode 100644 index f4881b4..0000000 --- a/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntity.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Text.Json; - -namespace ActivityPub.Types.Conversion.Overrides; - -/// -/// Indicates that the entity's presence in an object cannot be detected by any built-in method. -/// Exposes functionality to dynamically detect the entity within an arbitrary JSON message. -/// -/// -/// -public interface IAnonymousEntity -{ - /// - /// Checks if this entity should be deserialized from the given JSON message. - /// - /// JSON message that is being converted. May not be an object. - /// Metadata that has already been parsed from the JSON. - public static abstract bool ShouldConvertFrom(JsonElement inputJson, DeserializationMetadata meta); -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntitySelector.cs b/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntitySelector.cs deleted file mode 100644 index 823d630..0000000 --- a/Source/ActivityPub.Types/Conversion/Overrides/IAnonymousEntitySelector.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Text.Json; - -namespace ActivityPub.Types.Conversion.Overrides; - - -/// -/// Examines an incoming JSON message to determine which - if any - anonymous entities should be converted from it. -/// This is intended for entities that can't implement directly. -/// -/// -public interface IAnonymousEntitySelector -{ - /// - /// Checks a JSON message to identify all anonymous entities within it. - /// - /// JSON message that is being converted. May not be an object. - /// Metadata that has already been parsed from the JSON. - public IEnumerable SelectAnonymousEntities(JsonElement inputJson, DeserializationMetadata meta); -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Overrides/ICustomConvertedEntity.cs b/Source/ActivityPub.Types/Conversion/Overrides/ICustomConvertedEntity.cs deleted file mode 100644 index 408a608..0000000 --- a/Source/ActivityPub.Types/Conversion/Overrides/ICustomConvertedEntity.cs +++ /dev/null @@ -1,36 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Text.Json; -using System.Text.Json.Nodes; - -namespace ActivityPub.Types.Conversion.Overrides; - -/// -/// An entity that requires custom JSON conversion logic. -/// -public interface ICustomConvertedEntity - where TEntity : ASEntity, ICustomConvertedEntity -{ - /// - /// Converts the entity from a JSON message. - /// Return to bypass and trigger built-in default logic. - /// - public static virtual TEntity? ReadEntity(JsonElement jsonElement, DeserializationMetadata meta) => null; - - /// - /// Called after the entity is converted from JSON. - /// - public static virtual void PostReadEntity(JsonElement jsonElement, DeserializationMetadata meta, TEntity entity) {} - - /// - /// Converts the entity into a JSON message. - /// Return to bypass and trigger built-in default logic. - /// - public static virtual JsonElement? WriteEntity(TEntity entity, SerializationMetadata meta) => null; - - /// - /// Called after the object is converted to JSON. - /// - public static virtual void PostWriteEntity(TEntity entity, SerializationMetadata meta, JsonElement entityJson, JsonObject outputJson) {} -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Conversion/Overrides/INamelessEntity.cs b/Source/ActivityPub.Types/Conversion/Overrides/INamelessEntity.cs deleted file mode 100644 index 238f574..0000000 --- a/Source/ActivityPub.Types/Conversion/Overrides/INamelessEntity.cs +++ /dev/null @@ -1,21 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using ActivityPub.Types.Util; - -namespace ActivityPub.Types.Conversion.Overrides; - -/// -/// Indicates that the entity's presence in an object cannot be determined by AS type name alone. -/// Instead, nameless entities are identified by the JSON-LD context. -/// -/// -public interface INamelessEntity -{ - /// - /// Checks if this entity should be included by the given JSON-LD context. - /// - /// JSON-LD context that describes the JSON message. - /// Metadata that has already been parsed from the JSON. - public static abstract bool ShouldConvertFrom(IJsonLDContext jsonLDContext, DeserializationMetadata meta); -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/IASModel.cs b/Source/ActivityPub.Types/IASModel.cs index e5a26c4..1129d28 100644 --- a/Source/ActivityPub.Types/IASModel.cs +++ b/Source/ActivityPub.Types/IASModel.cs @@ -1,9 +1,12 @@ // This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. // If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. +using System.Text.Json; using System.Text.Json.Serialization; using ActivityPub.Types.AS; +using ActivityPub.Types.Internal; using ActivityPub.Types.Util; +using JetBrains.Annotations; namespace ActivityPub.Types; @@ -39,6 +42,23 @@ public interface IASModel /// The provided instance is guaranteed to include an instance of type . /// public static abstract TModel FromGraph(TypeMap typeMap); + + /// + /// Overrides the native type-matching logic. + /// This will be called when an object is being converted to check if it contains this type. + /// Return to forcibly parse the type, to block parsing, or to resume native logic. + /// + /// JSON message that is being converted. May not be an object. + /// Type graph that may contain the object. Contains the JSON-LD context and other metadata. + [PublicAPI] + public static virtual bool? ShouldConvertFrom(JsonElement inputJson, TypeMap typeMap) => null; + + /// + /// AS name of all types that derive from this one. + /// + /// + internal static virtual HashSet? DerivedTypeNames => ASNameTree.GetDerivedTypesFor(TModel.ASTypeName); + static IASModel() => ASNameTree.Add(TModel.ASTypeName, TModel.BaseTypeName); } /// diff --git a/Source/ActivityPub.Types/Internal/ASNameTree.cs b/Source/ActivityPub.Types/Internal/ASNameTree.cs new file mode 100644 index 0000000..7a97528 --- /dev/null +++ b/Source/ActivityPub.Types/Internal/ASNameTree.cs @@ -0,0 +1,79 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +using System.Runtime.CompilerServices; +using ActivityPub.Types.AS; + +namespace ActivityPub.Types.Internal; + +internal static class ASNameTree +{ + private static readonly Dictionary NameBaseMap = new(); + private static readonly Dictionary> NameDescendentsMap = new(); + + public static void Add(string? asTypeName, string? baseTypeName) + { + if (asTypeName == null || baseTypeName == null) + return; + + // When adding a new entry, we may be filling in a gap. + // If so, then we need to "promote" the existing descendents up to the base(s). + if ( + NameBaseMap.TryAdd(asTypeName, baseTypeName) && + NameDescendentsMap.TryGetValue(asTypeName, out var existingDescendents)) + { + foreach (var descendentName in existingDescendents) + { + AddRecursive(baseTypeName, descendentName); + } + } + + // We have to recursively update all base types + AddRecursive(baseTypeName, asTypeName); + } + + private static void AddRecursive(string? asTypeName, string descendentTypeName) + { + if (asTypeName == null) + return; + + do + { + if (!NameDescendentsMap.TryGetValue(asTypeName, out var derivedTypes)) + { + derivedTypes = new HashSet(); + NameDescendentsMap[asTypeName] = derivedTypes; + } + + derivedTypes.Add(descendentTypeName); + } while (NameBaseMap.TryGetValue(asTypeName, out asTypeName)); + } + + public static HashSet? GetDerivedTypesFor(string? asTypeName) + { + if (asTypeName != null && NameDescendentsMap.TryGetValue(asTypeName, out var derivedTypes)) + return derivedTypes; + + return null; + } + + + /// + /// Static constructor to ensure that all AS types have been statically initialized. + /// The CLR will not automatically call static initializers in interfaces. + /// https://stackoverflow.com/questions/5299737/static-constructor-on-a-net-interface-is-not-run + /// https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.runtimehelpers.runclassconstructor?view=net-8.0 + /// + static ASNameTree() + { + var interfaceTypes = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => a.GetTypes()) + .Where(t => t.IsAssignableTo(typeof(ASType))) + .SelectMany(t => t.GetInterfaces()); + + foreach (var type in interfaceTypes) + { + RuntimeHelpers.RunClassConstructor(type.TypeHandle); + } + } +} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Internal/CompositeASType.cs b/Source/ActivityPub.Types/Internal/CompositeASType.cs index f6d2e93..f6e630c 100644 --- a/Source/ActivityPub.Types/Internal/CompositeASType.cs +++ b/Source/ActivityPub.Types/Internal/CompositeASType.cs @@ -35,9 +35,8 @@ internal class CompositeASType public void Add(string type, string? replacedType = null) { // Add it to the superset. - // This doubles as a duplicate check to avoid extra set operations. - if (!_allASTypes.Add(type)) - return; + // This may happen repeatedly as a type graph is hydrated. + _allASTypes.Add(type); // Replace the base type if (replacedType != null) @@ -50,4 +49,16 @@ public void Add(string type, string? replacedType = null) if (!_replacedASTypes.Contains(type)) _flatASTypes.Add(type); } + + /// + /// Adds a collection of type names. + /// These are assumed to to not shadow anything, but may be shadowed by existing types. + /// + public void AddRange(IEnumerable asTypes) + { + foreach (var asType in asTypes) + { + Add(asType); + } + } } \ No newline at end of file diff --git a/Source/ActivityPub.Types/Internal/Pivots/AnonymousEntityPivot.cs b/Source/ActivityPub.Types/Internal/Pivots/AnonymousEntityPivot.cs deleted file mode 100644 index e7bc20e..0000000 --- a/Source/ActivityPub.Types/Internal/Pivots/AnonymousEntityPivot.cs +++ /dev/null @@ -1,50 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Reflection; -using System.Text.Json; -using ActivityPub.Types.Conversion.Overrides; - -namespace ActivityPub.Types.Internal.Pivots; - -internal class AnonymousEntityPivot -{ - private readonly Dictionary _anonymousCheckerCache = new(); - private readonly Func _createAnonymousChecker = - typeof(AnonymousEntityPivot) - .GetRequiredMethod(nameof(CreateAnonymousChecker), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotFunc(); - - public bool ShouldConvert(Type entityType, JsonElement jsonElement, DeserializationMetadata meta) - { - var checker = GetAnonymousChecker(entityType); - return checker.ShouldConvert(jsonElement, meta); - } - - private AnonymousChecker GetAnonymousChecker(Type entityType) - { - if (!_anonymousCheckerCache.TryGetValue(entityType, out var checker)) - { - checker = _createAnonymousChecker(entityType); - _anonymousCheckerCache[entityType] = checker; - } - - return checker; - } - - private static AnonymousChecker CreateAnonymousChecker() - where TEntity : IAnonymousEntity - => new AnonymousChecker(); - - private abstract class AnonymousChecker - { - public abstract bool ShouldConvert(JsonElement jsonElement, DeserializationMetadata meta); - } - - private class AnonymousChecker : AnonymousChecker - where T : IAnonymousEntity - { - public override bool ShouldConvert(JsonElement jsonElement, DeserializationMetadata meta) - => T.ShouldConvertFrom(jsonElement, meta); - } -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Internal/Pivots/CustomConvertedEntityPivot.cs b/Source/ActivityPub.Types/Internal/Pivots/CustomConvertedEntityPivot.cs deleted file mode 100644 index b59fef7..0000000 --- a/Source/ActivityPub.Types/Internal/Pivots/CustomConvertedEntityPivot.cs +++ /dev/null @@ -1,126 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Nodes; -using ActivityPub.Types.Conversion.Overrides; - -namespace ActivityPub.Types.Internal.Pivots; - -internal class CustomConvertedEntityPivot -{ - private readonly Dictionary _knownCustomConverters = new(); - - /// - /// Pivots to from a provided as first argument. - /// - private readonly Func _readEntityPivot = - typeof(CustomConvertedEntityPivot) - .GetRequiredMethod(nameof(ReadEntity), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotFunc(); - - /// - /// Pivots to from a provided as first argument. - /// - private readonly Action _postReadEntityPivot = - typeof(CustomConvertedEntityPivot) - .GetRequiredMethod(nameof(PostReadEntity), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotAction(); - - /// - /// Pivots to from a provided as first argument. - /// - private readonly Func _writeEntityPivot = - typeof(CustomConvertedEntityPivot) - .GetRequiredMethod(nameof(WriteEntity), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotFunc(); - - /// - /// Pivots to from a provided as first argument. - /// - private readonly Action _postWriteEntityPivot = - typeof(CustomConvertedEntityPivot) - .GetRequiredMethod(nameof(PostWriteEntity), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotAction(); - - - public ASEntity? ReadEntity(Type entityType, JsonElement jsonElement, DeserializationMetadata meta) - { - if (IsCustomConverted(entityType)) - return _readEntityPivot(entityType, jsonElement, meta); - - return null; - } - - public void PostReadEntity(Type entityType, JsonElement jsonElement, DeserializationMetadata meta, ASEntity entity) - { - if (IsCustomConverted(entityType)) - _postReadEntityPivot(entityType, jsonElement, meta, entity); - } - - public JsonElement? WriteEntity(Type entityType, ASEntity entity, SerializationMetadata meta) - { - if (IsCustomConverted(entityType)) - return _writeEntityPivot(entityType, entity, meta); - - return null; - } - - public void PostWriteEntity(Type entityType, ASEntity entity, SerializationMetadata meta, JsonElement entityJson, JsonObject outputJson) - { - if (IsCustomConverted(entityType)) - _postWriteEntityPivot(entityType, entity, meta, entityJson, outputJson); - } - - /// - /// Checks if a provided entity type is an implementation of . - /// - private bool IsCustomConverted(Type entityType) - { - if (!_knownCustomConverters.TryGetValue(entityType, out var isCustomConverted)) - { - // This is all just a complicated way to avoid a crash in the case where entityType does *not* implement ICustomConvertedEntity - if (typeof(ICustomConvertedEntity<>).TryMakeGenericType(out var interfaceType, entityType)) - isCustomConverted = entityType.IsAssignableTo(interfaceType); - else - isCustomConverted = false; - - _knownCustomConverters.Add(entityType, isCustomConverted); - } - - return isCustomConverted; - } - - - /// - /// Calls for a given type of TEntity. - /// - private static TEntity? ReadEntity(JsonElement jsonElement, DeserializationMetadata meta) - where TEntity : ASEntity, ICustomConvertedEntity - => TEntity.ReadEntity(jsonElement, meta); - - /// - /// Calls for a given type of TEntity. - /// Parameter types are relaxed to simplify generic binding. - /// - private static void PostReadEntity(JsonElement jsonElement, DeserializationMetadata meta, ASEntity entity) - where TEntity : ASEntity, ICustomConvertedEntity - => TEntity.PostReadEntity(jsonElement, meta, (TEntity)entity); - - /// - /// Calls for a given type of TEntity. - /// Parameter types are relaxed to simplify generic binding. - /// - private static JsonElement? WriteEntity(ASEntity entity, SerializationMetadata meta) - where TEntity : ASEntity, ICustomConvertedEntity - => TEntity.WriteEntity((TEntity)entity, meta); - - /// - /// Calls for a given type of TEntity. - /// Parameter types are relaxed to simplify generic binding. - /// - private static void PostWriteEntity(ASEntity entity, SerializationMetadata meta, JsonElement entityJson, JsonObject outputJson) - where TEntity : ASEntity, ICustomConvertedEntity - => TEntity.PostWriteEntity((TEntity)entity, meta, entityJson, outputJson); -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Internal/Pivots/NamelessEntityPivot.cs b/Source/ActivityPub.Types/Internal/Pivots/NamelessEntityPivot.cs deleted file mode 100644 index b36849d..0000000 --- a/Source/ActivityPub.Types/Internal/Pivots/NamelessEntityPivot.cs +++ /dev/null @@ -1,49 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Reflection; -using ActivityPub.Types.Conversion.Overrides; - -namespace ActivityPub.Types.Internal.Pivots; - -internal class NamelessEntityPivot -{ - private readonly Dictionary _namelessCheckerCache = new(); - private readonly Func _createNamelessChecker = - typeof(NamelessEntityPivot) - .GetRequiredMethod(nameof(CreateNamelessChecker), BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) - .CreateGenericPivotFunc(); - - public bool ShouldConvert(Type entityType, DeserializationMetadata meta) - { - var checker = GetNamelessChecker(entityType); - return checker.ShouldConvert(meta); - } - - private NamelessChecker GetNamelessChecker(Type entityType) - { - if (!_namelessCheckerCache.TryGetValue(entityType, out var checker)) - { - checker = _createNamelessChecker(entityType); - _namelessCheckerCache[entityType] = checker; - } - - return checker; - } - - private static NamelessChecker CreateNamelessChecker() - where TEntity : INamelessEntity - => new NamelessChecker(); - - private abstract class NamelessChecker - { - public abstract bool ShouldConvert(DeserializationMetadata meta); - } - - private class NamelessChecker : NamelessChecker - where T : INamelessEntity - { - public override bool ShouldConvert(DeserializationMetadata meta) - => T.ShouldConvertFrom(meta.LDContext, meta); - } -} \ No newline at end of file diff --git a/Source/ActivityPub.Types/Internal/TypeGraphReader.cs b/Source/ActivityPub.Types/Internal/TypeGraphReader.cs new file mode 100644 index 0000000..23a0818 --- /dev/null +++ b/Source/ActivityPub.Types/Internal/TypeGraphReader.cs @@ -0,0 +1,132 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using ActivityPub.Types.AS; +using ActivityPub.Types.Util; + +namespace ActivityPub.Types.Internal; + +internal interface ITypeGraphReader +{ + public JsonLDContext GetASContext(); + public List GetASTypes(); + + public bool TryReadEntity(TypeMap typeMap, [NotNullWhen(true)] out TEntity? entity) + where TModel : ASType, IASModel + where TEntity : ASEntity, new(); + + public bool TryReadEntity(TypeMap typeMap, [NotNullWhen(true)] out ASEntity? entity) + where TModel : ASType, IASModel; +} + +internal class TypeGraphReader : ITypeGraphReader +{ + private readonly JsonSerializerOptions _jsonOptions; + private readonly JsonElement _sourceElement; + + private readonly JsonLDContext _context; + private readonly HashSet _asTypes; + + public TypeGraphReader(JsonSerializerOptions jsonOptions, JsonElement sourceElement) + { + _jsonOptions = jsonOptions; + _sourceElement = sourceElement; + + if (sourceElement.ValueKind != JsonValueKind.Object) + throw new ArgumentException($"{nameof(TypeGraphReader)} can only convert JSON objects. Input is of type {sourceElement.ValueKind}.", nameof(sourceElement)); + + _context = ReadASContext(_sourceElement, _jsonOptions); + _asTypes = ReadASTypes(_sourceElement, _jsonOptions); + } + + public JsonLDContext GetASContext() + => _context.Clone(); + + public List GetASTypes() + => _asTypes.ToList(); + + + public bool TryReadEntity(TypeMap typeMap, [NotNullWhen(true)] out TEntity? entity) + where TModel : ASType, IASModel + where TEntity : ASEntity, new() + { + var shouldConvert = TModel.ShouldConvertFrom(_sourceElement, typeMap) ?? ShouldConvertObject(); + if (shouldConvert) + { + entity = _sourceElement.Deserialize(_jsonOptions) + ?? throw new JsonException($"Failed to deserialize {TModel.EntityType} - JsonElement.Deserialize returned null"); + return true; + } + + entity = null; + return false; + } + + public bool TryReadEntity(TypeMap typeMap, [NotNullWhen(true)] out ASEntity? entity) + where TModel : ASType, IASModel + { + var shouldConvert = TModel.ShouldConvertFrom(_sourceElement, typeMap) ?? ShouldConvertObject(); + if (shouldConvert) + { + entity = (ASEntity?)_sourceElement.Deserialize(TModel.EntityType, _jsonOptions) + ?? throw new JsonException($"Failed to deserialize {TModel.EntityType} - JsonElement.Deserialize returned null"); + return true; + } + + entity = null; + return false; + } + + private bool ShouldConvertObject() + where TModel : ASType, IASModel + { + // Check context first + if (!_context.IsSupersetOf(TModel.DefiningContext)) + return false; + + // If this is a nameless entity, then we're done. + if (TModel.ASTypeName == null) + return true; + + // Next, we need to check the AS type name. + if (_asTypes.Contains(TModel.ASTypeName)) + return true; + + // Finally, we need to check the AS type name of all *derived* types. + // Otherwise, an object like {"type":"Create"} would not be detected as a type of Activity. + // This is non-trivial, as we must do this without reflection (this code is on the hot path). + // Fortunately, most of the work is done for us by ASNameTree. + var derivedTypes = TModel.DerivedTypeNames; + return derivedTypes != null && _asTypes.Overlaps(derivedTypes); + } + + private static JsonLDContext ReadASContext(JsonElement element, JsonSerializerOptions options) + { + // Try to get the context property. + if (!element.TryGetProperty("@context", out var contextProp)) + // If missing then use default. + return JsonLDContext.CreateASContext(); + + // Convert context + return contextProp.Deserialize(options) + ?? throw new JsonException("Can't convert TypeMap - \"@context\" property is null"); + } + + private static HashSet ReadASTypes(JsonElement element, JsonSerializerOptions options) + { + // An object without the types field is just "object" + if (!element.TryGetProperty("type", out var typeProp)) + return new HashSet + { + ASObject.ObjectType + }; + + // Everything thing else must be converted + var types = typeProp.Deserialize>(options) + ?? throw new JsonException("Can't convert TypeMap - \"type\" is null"); + types.Add(ASObject.ObjectType); + return types; + } +} \ No newline at end of file diff --git a/Source/ActivityPub.Types/TypeMap.cs b/Source/ActivityPub.Types/TypeMap.cs index e79951a..a58117d 100644 --- a/Source/ActivityPub.Types/TypeMap.cs +++ b/Source/ActivityPub.Types/TypeMap.cs @@ -27,18 +27,41 @@ public class TypeMap // Cache of entity classes that have been added to this type graph. private readonly Dictionary _entityCache = new(); + // Optional JSON wrapper to source missing data. + private readonly ITypeGraphReader? _sourceJson; + /// /// Constructs a new, empty type graph initialized with the ActivityStreams context. /// - public TypeMap() : this(JsonLDContext.CreateASContext()) {} + public TypeMap() => _ldContext = JsonLDContext.CreateASContext(); + + /// + /// Constructs a TypeMap from a JSON message + /// + internal TypeMap(ITypeGraphReader sourceJson) + { + _sourceJson = sourceJson; + _ldContext = sourceJson.GetASContext(); + _asTypes.AddRange(sourceJson.GetASTypes()); + } /// - /// Constructs a TypeMap with a pre-populated JSON-LD context. + /// Constructs an empty TypeMap from pre-constructed context. + /// The caller is responsible for populating any associated entities. /// - /// + /// + /// This constructor is required to convert links in string-form. + /// That specific case is not supported by . + /// + internal TypeMap(JsonLDContext ldContext, IEnumerable asTypes) + { + _ldContext = ldContext; + _asTypes.AddRange(asTypes); + } + + /// internal TypeMap(JsonLDContext ldContext) => _ldContext = ldContext; - /// /// public IReadOnlySet ASTypes => _asTypes.Types; @@ -71,45 +94,56 @@ public TypeMap() : this(JsonLDContext.CreateASContext()) {} /// /// Checks if the object contains a particular entity type. /// - public bool IsEntity() - where TEntity : ASEntity - => _entityCache.ContainsKey(typeof(TEntity)); - + public bool IsEntity() + where TModel : ASType, IASModel + where TEntity : ASEntity, new() + => IsEntity(out _); + /// /// Checks if the object contains a particular type entity. /// If so, then the instance of that type is extracted and returned. /// - /// - /// - public bool IsEntity([NotNullWhen(true)] out TEntity? instance) - where TEntity : ASEntity + /// + /// + public bool IsEntity([NotNullWhen(true)] out TEntity? instance) + where TModel : ASType, IASModel + where TEntity : ASEntity, new() { + // 1. See if the entity is already in the type if (_entityCache.TryGetValue(typeof(TEntity), out var instanceT)) { instance = (TEntity)instanceT; return true; } - + + // 2. See if we can construct the entity from JSON + if (_sourceJson != null && _sourceJson.TryReadEntity(this, out instance)) + { + AddEntity(instance); + return true; + } + instance = null; return false; } - + /// /// Gets an entity representing the object as entity type TEntity. /// /// /// This function will not extend the object to include a new type. - /// To safely convert to an instance that *might* be present, use . + /// To safely convert to an instance that *might* be present, use . /// - /// + /// /// If the object is not of type TEntity - public TEntity AsEntity() - where TEntity : ASEntity + public TEntity AsEntity() + where TModel : ASType, IASModel + where TEntity : ASEntity, new() { - var type = typeof(TEntity); - if (!_entityCache.TryGetValue(type, out var instance)) - throw new InvalidCastException($"Can't represent the graph as entity {typeof(TEntity)}"); - return (TEntity)instance; + if (IsEntity(out var entity)) + return entity; + + throw new InvalidCastException($"Can't represent the graph as entity {typeof(TEntity)}"); } /// @@ -119,20 +153,7 @@ public TEntity AsEntity() /// public bool IsModel() where TModel : ASType, IASModel - { - var type = typeof(TModel); - - // Already cached -> yes - if (_modelCache.ContainsKey(type)) - return true; - - // Can create it (entity is in the graph) -> yes - if (_entityCache.ContainsKey(TModel.EntityType)) - return true; - - // Otherwise -> no - return false; - } + => IsModel(out _); /// /// Checks if the graph contains a particular model type. @@ -159,6 +180,15 @@ public bool IsModel([NotNullWhen(true)] out TModel? instance) _modelCache[type] = instance; return true; } + + // Fallback can create it (entity is NOT in the graph) -> yes + if (_sourceJson != null && _sourceJson.TryReadEntity(this, out var entity)) + { + AddEntity(entity); + instance = TModel.FromGraph(this); + _modelCache[type] = instance; + return true; + } // Otherwise -> no instance = null; @@ -175,13 +205,13 @@ public bool IsModel([NotNullWhen(true)] out TModel? instance) /// /// /// If the graph cannot be represented by the type - public TObject AsModel() - where TObject : ASType, IASModel + public TModel AsModel() + where TModel : ASType, IASModel { - if (IsModel(out var instance)) + if (IsModel(out var instance)) return instance; - throw new InvalidCastException($"Can't represent the graph as type {typeof(TObject)}"); + throw new InvalidCastException($"Can't represent the graph as type {typeof(TModel)}"); } /// @@ -191,18 +221,19 @@ public TObject AsModel() /// /// /// This function cannot accomodate entities with required members. - /// Instead, must be used. + /// Instead, must be used. /// /// If extendGraph is and the entity type already exists in the graph /// If extendGraph is and the entity requires another entity that is missing from the graph /// If extendGraph is and the object is not of type TEntity - /// - /// - public TEntity ProjectTo(bool extendGraph) - where TEntity : ASEntity, new() + /// + /// + public TEntity ProjectTo(bool extendGraph) + where TModel : ASType, IASModel + where TEntity : ASEntity, new() => extendGraph - ? Extend() - : AsEntity(); + ? Extend() + : AsEntity(); /// /// Extends the TypeGraph to include a new entity. @@ -211,33 +242,32 @@ public TEntity ProjectTo(bool extendGraph) /// /// /// This function cannot accomodate entities with required members. - /// Instead, must be used. + /// Instead, must be used. /// /// If the entity type already exists in the graph /// If the entity requires another entity that is missing from the graph - /// + /// /// /// - public TEntity Extend() - where TEntity : ASEntity, new() - => Extend(new TEntity()); + public TEntity Extend() + where TModel : ASType, IASModel + where TEntity : ASEntity, new() + => Extend(new TEntity()); /// /// Extends the TypeGraph to include a new entity. /// Throws an exception if the entity would be a duplicate or have unmet dependencies. /// - /// - /// - /// /// If the entity type already exists in the graph /// If the entity requires another entity that is missing from the graph - /// + /// /// /// - public TEntity Extend(TEntity entity) - where TEntity : ASEntity + public TEntity Extend(TEntity entity) + where TModel : ASType, IASModel + where TEntity : ASEntity, new() { - if (IsEntity()) + if (IsEntity()) throw new InvalidOperationException($"Cannot extend the graph with entity {typeof(TEntity)}: that type already exists in the graph"); // Check dependencies - this is a workaround to avoid the risk case described in TryAdd(). @@ -261,7 +291,7 @@ internal void AddEntity(ASEntity instance) /// /// Adds a new typed instance to the graph. /// Metadata such as AS types and JSON-LD context is automatically updated. - /// User code should not call this method; use instead. + /// User code should not call this method; use instead. /// /// /// @@ -281,22 +311,21 @@ internal void AddEntity(ASEntity instance) /// This can be extremely hard to diagnose because does not even appear in the visible code. /// /// - /// The function, however, avoids this with an included dependency check. + /// The function, however, avoids this with an included dependency check. /// The second call to will fail with a descriptive error message indicating that Object is missing from the graph. /// While still somewhat confusing, this method will additionally fail fast before the graph can even enter an invalid state. /// This ensures that errors are caught quickly and before they can spread to corrupt the application state. /// /// /// true if the type was added, false if it was already in the type map - /// + /// internal bool TryAddEntity(ASEntity entity) { var type = entity.GetType(); - if (_entityCache.ContainsKey(type)) - return false; - + // Map the instance - _entityCache[type] = entity; + if (!_entityCache.TryAdd(type, entity)) + return false; // Map the AS type if (entity.ASTypeName != null) @@ -330,10 +359,4 @@ private void NarrowUnmappedProperties(ASEntity entity) .ToList() .ForEach(k => UnmappedProperties.Remove(k)); } - - /// - /// Records an ActivityStreams type name as being present in the type graph, but not mapped to any known implementation class. - /// Duplicates will be ignored. - /// - internal void AddUnmappedType(string asTypeName) => _asTypes.Add(asTypeName); } \ No newline at end of file diff --git a/Source/ActivityPub.Types/TypesModule.cs b/Source/ActivityPub.Types/TypesModule.cs index 2805d9c..0f032df 100644 --- a/Source/ActivityPub.Types/TypesModule.cs +++ b/Source/ActivityPub.Types/TypesModule.cs @@ -25,15 +25,6 @@ public static void TryAddTypesModule(this IServiceCollection services) { services.TryAddSingleton(); - services.TryAddSingleton( - _ => - { - var cache = new ASTypeInfoCache(); - cache.RegisterAllAssemblies(); - return cache; - } - ); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Source/ActivityPub.Types/Util/JsonLDContext.cs b/Source/ActivityPub.Types/Util/JsonLDContext.cs index 36c1c72..1c75554 100644 --- a/Source/ActivityPub.Types/Util/JsonLDContext.cs +++ b/Source/ActivityPub.Types/Util/JsonLDContext.cs @@ -45,4 +45,9 @@ public JsonLDContext(IEnumerable objects) : base(objects) { { JsonLDContextObject.ActivityStreams }; + + /// + /// Creates a shallow copy of this Json-LD context. + /// + public JsonLDContext Clone() => new(this); } \ No newline at end of file diff --git a/Source/ActivityPub.Types/Util/Linkable.cs b/Source/ActivityPub.Types/Util/Linkable.cs index a333cb6..9682b5f 100644 --- a/Source/ActivityPub.Types/Util/Linkable.cs +++ b/Source/ActivityPub.Types/Util/Linkable.cs @@ -11,6 +11,7 @@ namespace ActivityPub.Types.Util; /// /// Type of element public sealed class Linkable + where T : ASType { /// /// Creates a Linkable from a reference link diff --git a/Source/ActivityPub.Types/Util/LinkableList.cs b/Source/ActivityPub.Types/Util/LinkableList.cs index fb1563d..fa44aa2 100644 --- a/Source/ActivityPub.Types/Util/LinkableList.cs +++ b/Source/ActivityPub.Types/Util/LinkableList.cs @@ -9,6 +9,7 @@ namespace ActivityPub.Types.Util; /// Synthetic type to represent a list of T or Links to T /// public class LinkableList : List> + where T : ASType { /// public LinkableList() {} diff --git a/Source/ActivityPub.Types/Util/NaturalLanguageString.cs b/Source/ActivityPub.Types/Util/NaturalLanguageString.cs index 56bcf85..828b69b 100644 --- a/Source/ActivityPub.Types/Util/NaturalLanguageString.cs +++ b/Source/ActivityPub.Types/Util/NaturalLanguageString.cs @@ -31,6 +31,12 @@ public string? DefaultValue public IReadOnlyDictionary LanguageMap => _languageMap; private readonly Dictionary _languageMap = new(); + /// + /// if this string contains any language-tagged values. + /// is ignored. + /// + public bool HasLanguages => _languageMap.Any(); + /// /// Constructs a NaturalLanguageString from a map of BCP47 Language-Tags. /// diff --git a/Source/ActivityPub.Types/readme.md b/Source/ActivityPub.Types/readme.md index 3af4ef7..e40b196 100644 --- a/Source/ActivityPub.Types/readme.md +++ b/Source/ActivityPub.Types/readme.md @@ -68,12 +68,9 @@ However, it will be necessary if implementing a new extension or handling some r ### Entity Mapping -APSharp includes a 4-step process to determine which entities should be constructed from an incoming JSON message. -All entities detected by at least one test will be converted and parsed. -1. Map values of the `type` property to registered AS type names. -2. Try all entities that implement [`INamelessEntity`](Conversion/Overrides/INamelessEntity.cs). -3. Try all entities that implement [`IAnonymousEntity`](Conversion/Overrides/IAnonymousEntity.cs). -4. Try all configured [`IAnonymousEntitySelector`](Conversion/Overrides/IAnonymousEntitySelector.cs) instances. +By default, APSharp checks the `@context` and `type` properties to determine whether an object can be projected to a given model or entity. +Entities without a type will be converted purely based on the context. +This logic can be altered by overriding `IASModel.ShouldConvertFrom` and performing additional checks. ## Utility Types @@ -138,4 +135,3 @@ See the [ActivityStreams documentation](https://www.w3.org/TR/activitystreams-co | Service | Implementation | Description | |-------------------------------------------------------|---------------------------------------------------------|-----------------------------------------------------------------------| | [`IJsonLdSerializer`](Conversion/JsonLdSerializer.cs) | [`JsonLdSerializer.cs`](Conversion/JsonLdSerializer.cs) | Parses and serializes ActivityStreams messages from JSON or JSON-LD. | -| [`IASTypeInfoCache`](Conversion/ASTypeInfoCache.cs) | [`ASTypeInfoCache`](Conversion/ASTypeInfoCache.cs) | Indexes metadata related to AS / AP types defined in the application. | diff --git a/Test/ActivityPub.Types.Tests/Integration/Deserialization/ExtensionDeserializationTests.cs b/Test/ActivityPub.Types.Tests/Integration/Deserialization/ExtensionDeserializationTests.cs index 85bdb67..bf38b1e 100644 --- a/Test/ActivityPub.Types.Tests/Integration/Deserialization/ExtensionDeserializationTests.cs +++ b/Test/ActivityPub.Types.Tests/Integration/Deserialization/ExtensionDeserializationTests.cs @@ -45,23 +45,6 @@ public void Convert_FromBothProperties() ObjectUnderTest.As().ExtendedString.Should().Be("Hello, world!"); ObjectUnderTest.As().ExtendedInt.Should().Be(123); } - - [Fact] - public void Convert_FromEntitySelector() - { - SerializerFixture.ConversionOptions.AnonymousEntitySelectors.Add - ( - new AnonymousEntitySelectorFake - { - PropertyNameMapping = - { - [nameof(ASActivity.Actor)] = typeof(ASActivityEntity) - } - } - ); - JsonUnderTest = """{"@context":"https://www.w3.org/ns/activitystreams","type":"Object","Actor":{}}"""; - ObjectUnderTest.Is().Should().BeTrue(); - } public AnonymousExtensionsShould(JsonLdSerializerFixture fixture) : base(fixture) {} } diff --git a/Test/ActivityPub.Types.Tests/Integration/Serialization/ObjectSerializationTests.cs b/Test/ActivityPub.Types.Tests/Integration/Serialization/ObjectSerializationTests.cs index 8e8b35c..78ec164 100644 --- a/Test/ActivityPub.Types.Tests/Integration/Serialization/ObjectSerializationTests.cs +++ b/Test/ActivityPub.Types.Tests/Integration/Serialization/ObjectSerializationTests.cs @@ -61,6 +61,7 @@ public void WriteDefaultValueToContentJson() }; JsonUnderTest.Should().HaveStringProperty("content", "default"); + JsonUnderTest.Should().NotHaveProperty("contentMap"); } [Fact] diff --git a/Test/ActivityPub.Types.Tests/Integration/Serialization/ValueStripSerializationTests.cs b/Test/ActivityPub.Types.Tests/Integration/Serialization/ValueStripSerializationTests.cs index 60c89c4..33aad32 100644 --- a/Test/ActivityPub.Types.Tests/Integration/Serialization/ValueStripSerializationTests.cs +++ b/Test/ActivityPub.Types.Tests/Integration/Serialization/ValueStripSerializationTests.cs @@ -122,11 +122,11 @@ public class FakeObjectWithSpecialNullability : ASObject, IASModel.ASTypeName => FakeObjectWithSpecialNullabilityType; /// - public FakeObjectWithSpecialNullability() => Entity = TypeMap.Extend(); + public FakeObjectWithSpecialNullability() => Entity = TypeMap.Extend(); /// public FakeObjectWithSpecialNullability(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public FakeObjectWithSpecialNullability(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -134,7 +134,7 @@ public FakeObjectWithSpecialNullability(ASType existingGraph) : this(existingGra /// [SetsRequiredMembers] public FakeObjectWithSpecialNullability(TypeMap typeMap, FakeObjectWithSpecialNullabilityEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static FakeObjectWithSpecialNullability IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Test/ActivityPub.Types.Tests/Unit/AS/ASTypeTests.cs b/Test/ActivityPub.Types.Tests/Unit/AS/ASTypeTests.cs index e0eae47..0f01654 100644 --- a/Test/ActivityPub.Types.Tests/Unit/AS/ASTypeTests.cs +++ b/Test/ActivityPub.Types.Tests/Unit/AS/ASTypeTests.cs @@ -74,11 +74,11 @@ private class StubASType : ASType, IASModel.ASTypeName => StubType; /// - public StubASType() => Entity = TypeMap.Extend(); + public StubASType() => Entity = TypeMap.Extend(); /// public StubASType(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public StubASType(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -86,7 +86,7 @@ public StubASType(ASType existingGraph) : this(existingGraph.TypeMap) {} /// [SetsRequiredMembers] public StubASType(TypeMap typeMap, StubASTypeEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static StubASType IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Test/ActivityPub.Types.Tests/Unit/Internal/ASTypeInfoCacheTests.cs b/Test/ActivityPub.Types.Tests/Unit/Internal/ASTypeInfoCacheTests.cs deleted file mode 100644 index 6f75f11..0000000 --- a/Test/ActivityPub.Types.Tests/Unit/Internal/ASTypeInfoCacheTests.cs +++ /dev/null @@ -1,124 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using System.Diagnostics.CodeAnalysis; -using ActivityPub.Types.AS; -using ActivityPub.Types.Conversion; -using ActivityPub.Types.Conversion.Overrides; -using ActivityPub.Types.Tests.Util.Fakes; -using ActivityPub.Types.Util; - -namespace ActivityPub.Types.Tests.Unit.Internal; - -public abstract class ASTypeInfoCacheTests -{ - private ASTypeInfoCache CacheUnderTest { get; } = new(); - - public class RegisterAllAssembliesShould : ASTypeInfoCacheTests - { - public RegisterAllAssembliesShould() => CacheUnderTest.RegisterAllAssemblies(); - - [Fact] - public void IncludeTypesPackage() - { - CacheUnderTest.TryGetModelType(ASObject.ObjectType, out _).Should().BeTrue(); - } - - [Fact] - public void IncludeOtherPackages() - { - CacheUnderTest.TryGetModelType(FakeTypeForASTypeInfoCacheTests.FakeTypeForASTypeInfoCacheTestsType, out _).Should().BeTrue(); - } - } - - public class RegisterAssemblyShould : ASTypeInfoCacheTests - { - public RegisterAssemblyShould() => CacheUnderTest.RegisterAssembly(typeof(ASObjectEntity).Assembly); - - [Fact] - public void IncludeThatAssembly() - { - CacheUnderTest.TryGetModelType(ASObject.ObjectType, out _).Should().BeTrue(); - } - - [Fact] - public void NotIncludeOtherAssemblies() - { - CacheUnderTest.TryGetModelType(FakeTypeForASTypeInfoCacheTests.FakeTypeForASTypeInfoCacheTestsType, out _).Should().BeFalse(); - } - } - - public class AnonymousEntityTypesShould : ASTypeInfoCacheTests - { - public AnonymousEntityTypesShould() => CacheUnderTest.RegisterAllAssemblies(); - - [Fact] - public void IncludeAllDetectedAnonymousTypes() - { - var expectedType = typeof(AnonymousExtensionFakeEntity); - CacheUnderTest.AnonymousEntityTypes.Should().Contain(expectedType); - } - - [Fact] - public void ExcludeInvalidAnonymousTypes() - { - var unexpectedType = typeof(FakeTypeWithInvalidInterfaces); - CacheUnderTest.AnonymousEntityTypes.Should().NotContain(unexpectedType); - } - } - - public class NamelessEntityTypesShould : ASTypeInfoCacheTests - { - public NamelessEntityTypesShould() => CacheUnderTest.RegisterAllAssemblies(); - - [Fact] - public void IncludeAllDetectedNamelessTypes() - { - var expectedType = typeof(NamelessExtensionFakeEntity); - CacheUnderTest.NamelessEntityTypes.Should().Contain(expectedType); - } - - [Fact] - public void ExcludeInvalidNamelessTypes() - { - var unexpectedType = typeof(FakeTypeWithInvalidInterfaces); - CacheUnderTest.NamelessEntityTypes.Should().NotContain(unexpectedType); - } - } -} - -public class FakeTypeWithInvalidInterfaces : ASType, IAnonymousEntity, INamelessEntity -{ - public static bool ShouldConvertFrom(JsonElement inputJson, DeserializationMetadata meta) => throw new NotSupportedException(); - public static bool ShouldConvertFrom(IJsonLDContext jsonLDContext, DeserializationMetadata meta) => throw new NotSupportedException(); -} - -public class FakeTypeForASTypeInfoCacheTests : ASLink, IASModel -{ - /// - /// ActivityStreams type name for "FakeTypeForASTypeInfoCacheTests" types. - /// - public const string FakeTypeForASTypeInfoCacheTestsType = "FakeTypeForASTypeInfoCacheTests"; - static string IASModel.ASTypeName => FakeTypeForASTypeInfoCacheTestsType; - - /// - public FakeTypeForASTypeInfoCacheTests() => Entity = TypeMap.Extend(); - - /// - public FakeTypeForASTypeInfoCacheTests(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); - - /// - public FakeTypeForASTypeInfoCacheTests(ASType existingGraph) : this(existingGraph.TypeMap) {} - - /// - [SetsRequiredMembers] - public FakeTypeForASTypeInfoCacheTests(TypeMap typeMap, FakeTypeForASTypeInfoCacheTestsEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); - - static FakeTypeForASTypeInfoCacheTests IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); - - private FakeTypeForASTypeInfoCacheTestsEntity Entity { get; } -} - -public class FakeTypeForASTypeInfoCacheTestsEntity : ASEntity {} \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Unit/Internal/AnonymousEntityPivotTests.cs b/Test/ActivityPub.Types.Tests/Unit/Internal/AnonymousEntityPivotTests.cs deleted file mode 100644 index 09f7e13..0000000 --- a/Test/ActivityPub.Types.Tests/Unit/Internal/AnonymousEntityPivotTests.cs +++ /dev/null @@ -1,50 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using ActivityPub.Types.AS; -using ActivityPub.Types.Conversion.Overrides; -using ActivityPub.Types.Internal.Pivots; -using ActivityPub.Types.Tests.Util.Fakes; -using ActivityPub.Types.Util; - -namespace ActivityPub.Types.Tests.Unit.Internal; - -public abstract class AnonymousEntityPivotTests -{ - private AnonymousEntityPivot PivotUnderTest { get; } = new(); - - private DeserializationMetadata StubDeserializationMetadata { get; } = new() - { - TypeMap = new TypeMap(), - JsonSerializerOptions = JsonSerializerOptions.Default, - LDContext = new JsonLDContext() - }; - - public class ShouldConvertShould : AnonymousEntityPivotTests - { - [Fact] - public void Throw_WhenTypeDoesNotImplementInterface() - { - Assert.ThrowsAny(() => - { - PivotUnderTest.ShouldConvert(typeof(ASType), new JsonElement(), StubDeserializationMetadata); - }); - } - - [Fact] - public void ReturnFalse_WhenMethodReturnsFalse() - { - var result = PivotUnderTest.ShouldConvert(typeof(AnonymousExtensionFakeEntity), new JsonElement(), StubDeserializationMetadata); - result.Should().BeFalse(); - } - - [Fact] - public void ReturnTrue_WhenMethodReturnsTrue() - { - const string Json = """{"ExtendedString":"value"}"""; - var jsonElement = JsonSerializer.Deserialize(Json); - var result = PivotUnderTest.ShouldConvert(typeof(AnonymousExtensionFakeEntity), jsonElement, StubDeserializationMetadata); - result.Should().BeTrue(); - } - } -} \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Unit/Internal/CompositeASTypeTests.cs b/Test/ActivityPub.Types.Tests/Unit/Internal/CompositeASTypeTests.cs deleted file mode 100644 index 597d19a..0000000 --- a/Test/ActivityPub.Types.Tests/Unit/Internal/CompositeASTypeTests.cs +++ /dev/null @@ -1,107 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using ActivityPub.Types.Internal; - -namespace ActivityPub.Types.Tests.Unit.Internal; - -public abstract class CompositeASTypeTests -{ - /// - /// Contents:
- ///
    - ///
  • Top-level types: 1.1, 1.2.1, 1.2.2, 1.3.1.1
  • - ///
  • Shadowed types: 1, 1.2, 1.3, 1.3.1
  • - ///
- ///
- private CompositeASType TypeUnderTest { get; } = new(); - - protected CompositeASTypeTests() - { - TypeUnderTest.Add("1"); - TypeUnderTest.Add("1.1", "1"); - TypeUnderTest.Add("1.2", "1"); - TypeUnderTest.Add("1.2.1", "1.2"); - TypeUnderTest.Add("1.2.2", "1.2"); - TypeUnderTest.Add("1.3", "1"); - TypeUnderTest.Add("1.3.1", "1.3"); - TypeUnderTest.Add("1.3.1.1", "1.3.1"); - } - - public class TypesShould : CompositeASTypeTests - { - [Fact] - public void ContainOnlyTopLevelTypes() - { - TypeUnderTest.Types.Should() - .HaveCount(4) - .And.Contain("1.1") - .And.Contain("1.2.1") - .And.Contain("1.2.2") - .And.Contain("1.3.1.1"); - } - } - - public class AllTypesShould : CompositeASTypeTests - { - [Fact] - public void ContainAllTypes() - { - TypeUnderTest.AllTypes.Should() - .HaveCount(8) - .And.Contain("1") - .And.Contain("1.1") - .And.Contain("1.2") - .And.Contain("1.2.1") - .And.Contain("1.2.2") - .And.Contain("1.3") - .And.Contain("1.3.1") - .And.Contain("1.3.1.1"); - } - } - - public class AddShould : CompositeASTypeTests - { - [Fact] - public void DoNothing_IfTypeIsDuplicate() - { - TypeUnderTest.Add("1"); - TypeUnderTest.Add("1.1", "1"); - - TypeUnderTest.AllTypes.Should().HaveCount(8); - } - - [Fact] - public void UpdateAllTypes_IfNotDuplicate() - { - TypeUnderTest.Add("1.4", "1"); - - TypeUnderTest.AllTypes.Should().Contain("1.4"); - } - - [Fact] - public void UpdateTypes_IfNotShadowed() - { - TypeUnderTest.Add("1.4", "1"); - - TypeUnderTest.Types.Should().Contain("1.4"); - } - - [Fact] - public void NotUpdateTypes_IfShadowed() - { - TypeUnderTest.Add("1.4.1", "1.4"); - TypeUnderTest.Add("1.4", "1"); - - TypeUnderTest.Types.Should().NotContain("1.4"); - } - - [Fact] - public void RemoveShadowedTypes() - { - TypeUnderTest.Add("1.1.1", "1.1"); - - TypeUnderTest.Types.Should().NotContain("1.1"); - } - } -} \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousEntitySelectorFake.cs b/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousEntitySelectorFake.cs deleted file mode 100644 index 74e5560..0000000 --- a/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousEntitySelectorFake.cs +++ /dev/null @@ -1,22 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -// If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -using ActivityPub.Types.Conversion.Overrides; -using ActivityPub.Types.Internal; - -namespace ActivityPub.Types.Tests.Util.Fakes; - -public class AnonymousEntitySelectorFake : IAnonymousEntitySelector -{ - public Dictionary PropertyNameMapping { get; set; } = new(); - - public IEnumerable SelectAnonymousEntities(JsonElement inputJson, DeserializationMetadata meta) - { - if (inputJson.ValueKind != JsonValueKind.Object) - yield break; - - foreach (var (propName, entityType) in PropertyNameMapping) - if (inputJson.HasProperty(propName)) - yield return entityType; - } -} \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousExtensionFake.cs b/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousExtensionFake.cs index 2b5b3ef..fe44bf2 100644 --- a/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousExtensionFake.cs +++ b/Test/ActivityPub.Types.Tests/Util/Fakes/AnonymousExtensionFake.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using ActivityPub.Types.AS; -using ActivityPub.Types.Conversion.Overrides; using ActivityPub.Types.Internal; namespace ActivityPub.Types.Tests.Util.Fakes; @@ -12,7 +11,7 @@ public class AnonymousExtensionFake : ASObject, IASModel public AnonymousExtensionFake(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public AnonymousExtensionFake(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -20,7 +19,7 @@ public AnonymousExtensionFake(ASType existingGraph) : this(existingGraph.TypeMap /// [SetsRequiredMembers] public AnonymousExtensionFake(TypeMap typeMap, AnonymousExtensionFakeEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static AnonymousExtensionFake IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); @@ -37,20 +36,14 @@ public int ExtendedInt get => Entity.ExtendedInt; set => Entity.ExtendedInt = value; } + + public static bool? ShouldConvertFrom(JsonElement inputJson, TypeMap typeMap) => + inputJson.HasProperty(nameof(ExtendedString)) + || inputJson.HasProperty(nameof(ExtendedInt)); } -public sealed class AnonymousExtensionFakeEntity : ASEntity, IAnonymousEntity +public sealed class AnonymousExtensionFakeEntity : ASEntity { public string ExtendedString { get; set; } = ""; public int ExtendedInt { get; set; } - - public static bool ShouldConvertFrom(JsonElement inputJson, DeserializationMetadata meta) - { - if (inputJson.ValueKind != JsonValueKind.Object) - return false; - - return - inputJson.HasProperty(nameof(ExtendedString)) || - inputJson.HasProperty(nameof(ExtendedInt)); - } } \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Util/Fakes/EmptyExtendedTypeFake.cs b/Test/ActivityPub.Types.Tests/Util/Fakes/EmptyExtendedTypeFake.cs index edabce0..8eea5ca 100644 --- a/Test/ActivityPub.Types.Tests/Util/Fakes/EmptyExtendedTypeFake.cs +++ b/Test/ActivityPub.Types.Tests/Util/Fakes/EmptyExtendedTypeFake.cs @@ -17,11 +17,11 @@ public class EmptyExtendedTypeFake : ASType, IASModel - public EmptyExtendedTypeFake() => Entity = TypeMap.Extend(); + public EmptyExtendedTypeFake() => Entity = TypeMap.Extend(); /// public EmptyExtendedTypeFake(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public EmptyExtendedTypeFake(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -29,7 +29,7 @@ public EmptyExtendedTypeFake(ASType existingGraph) : this(existingGraph.TypeMap) /// [SetsRequiredMembers] public EmptyExtendedTypeFake(TypeMap typeMap, EmptyExtendedTypeFakeEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static EmptyExtendedTypeFake IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); diff --git a/Test/ActivityPub.Types.Tests/Util/Fakes/NamessExtensionFake.cs b/Test/ActivityPub.Types.Tests/Util/Fakes/NamessExtensionFake.cs index 77f1bf2..c0940c3 100644 --- a/Test/ActivityPub.Types.Tests/Util/Fakes/NamessExtensionFake.cs +++ b/Test/ActivityPub.Types.Tests/Util/Fakes/NamessExtensionFake.cs @@ -3,26 +3,24 @@ using System.Diagnostics.CodeAnalysis; using ActivityPub.Types.AS; -using ActivityPub.Types.Conversion.Overrides; using ActivityPub.Types.Util; namespace ActivityPub.Types.Tests.Util.Fakes; public class NamelessExtensionFake : ASObject, IASModel { - public static JsonLDContextObject NamelessExtensionContext { get; }= "https://example.com/nameless"; static IJsonLDContext IASModel.DefiningContext { get; } = new JsonLDContext { JsonLDContextObject.ActivityStreams, - NamelessExtensionContext + "https://example.com/nameless" }; /// - public NamelessExtensionFake() => Entity = TypeMap.Extend(); + public NamelessExtensionFake() => Entity = TypeMap.Extend(); /// public NamelessExtensionFake(TypeMap typeMap, bool isExtending = true) : base(typeMap, false) - => Entity = TypeMap.ProjectTo(isExtending); + => Entity = TypeMap.ProjectTo(isExtending); /// public NamelessExtensionFake(ASType existingGraph) : this(existingGraph.TypeMap) {} @@ -30,7 +28,7 @@ public NamelessExtensionFake(ASType existingGraph) : this(existingGraph.TypeMap) /// [SetsRequiredMembers] public NamelessExtensionFake(TypeMap typeMap, NamelessExtensionFakeEntity? entity) : base(typeMap, null) - => Entity = entity ?? typeMap.AsEntity(); + => Entity = entity ?? typeMap.AsEntity(); static NamelessExtensionFake IASModel.FromGraph(TypeMap typeMap) => new(typeMap, null); @@ -49,11 +47,8 @@ public int ExtendedInt } } -public sealed class NamelessExtensionFakeEntity : ASEntity, INamelessEntity +public sealed class NamelessExtensionFakeEntity : ASEntity { public string ExtendedString { get; set; } = ""; public int ExtendedInt { get; set; } - - public static bool ShouldConvertFrom(IJsonLDContext jsonLDContext, DeserializationMetadata meta) - => jsonLDContext.Contains(NamelessExtensionFake.NamelessExtensionContext); } \ No newline at end of file diff --git a/Test/ActivityPub.Types.Tests/Util/Fixtures/JsonLdSerializerFixture.cs b/Test/ActivityPub.Types.Tests/Util/Fixtures/JsonLdSerializerFixture.cs index 863d350..7708103 100644 --- a/Test/ActivityPub.Types.Tests/Util/Fixtures/JsonLdSerializerFixture.cs +++ b/Test/ActivityPub.Types.Tests/Util/Fixtures/JsonLdSerializerFixture.cs @@ -3,8 +3,6 @@ using ActivityPub.Types.Conversion; using ActivityPub.Types.Conversion.Converters; -using ActivityPub.Types.Conversion.Overrides; -using ActivityPub.Types.Internal; using JetBrains.Annotations; using Microsoft.Extensions.Options; @@ -21,25 +19,18 @@ public sealed class JsonLdSerializerFixture { public JsonLdSerializerFixture() { - ASTypeInfoCache = new ASTypeInfoCache(); - ASTypeInfoCache.RegisterAllAssemblies(); - JsonLdSerializerOptions = new JsonLdSerializerOptions(); var serializerOptions = Options.Create(JsonLdSerializerOptions); - ConversionOptions = new ConversionOptions(); - var conversionOptions = Options.Create(ConversionOptions); - var typeMapConverter = new TypeMapConverter(ASTypeInfoCache, conversionOptions); + var typeMapConverter = new TypeMapConverter(); var asTypeConverter = new ASTypeConverter(); - var linkableConverter = new LinkableConverter(ASTypeInfoCache); + var linkableConverter = new LinkableConverter(); var listableConverter = new ListableConverter(); var listableReadOnlyConverter = new ListableReadOnlyConverter(); JsonLdSerializer = new JsonLdSerializer(serializerOptions, typeMapConverter, asTypeConverter, linkableConverter, listableConverter, listableReadOnlyConverter); } - internal IASTypeInfoCache ASTypeInfoCache { get; } internal IJsonLdSerializer JsonLdSerializer { get; } internal JsonLdSerializerOptions JsonLdSerializerOptions { get; } - internal ConversionOptions ConversionOptions { get; } } \ No newline at end of file