Browse Source

Discriminator fixes for json schema.

pull/337/head
Sebastian Stehle 8 years ago
parent
commit
d75c2ccfa9
  1. 141
      src/Squidex/Areas/Api/Controllers/JsonInheritanceConverter.cs
  2. 49
      src/Squidex/Areas/Api/Controllers/MyJsonInheritanceConverter.cs
  3. 6
      src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs
  4. 2
      src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs
  5. 2
      src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionSerializer.cs
  6. 2
      src/Squidex/Areas/Api/Controllers/Rules/Models/RuleTriggerDto.cs
  7. 4
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/AssetChangedRuleTriggerDto.cs
  8. 6
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerDto.cs
  9. 2
      src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerSchemaDto.cs
  10. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldPropertiesDto.cs
  11. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ArrayFieldPropertiesDto.cs
  12. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs
  13. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs
  14. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs
  15. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs
  16. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/JsonFieldPropertiesDto.cs
  17. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs
  18. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs
  19. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs
  20. 2
      src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs
  21. 2
      src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs

141
src/Squidex/Areas/Api/Controllers/JsonInheritanceConverter.cs

@ -1,141 +0,0 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NJsonSchema.Annotations;
#pragma warning disable SA1306 // Field names must begin with lower-case letter
namespace Squidex.Areas.Api.Controllers
{
public class JsonInheritanceConverter : JsonConverter
{
private readonly string discriminator;
private readonly Dictionary<string, Type> mapTypeToName = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary<Type, string> mapNameToType = new Dictionary<Type, string>();
[ThreadStatic]
private static bool IsReading;
[ThreadStatic]
private static bool IsWriting;
public string DiscriminatorName
{
get { return discriminator; }
}
public override bool CanWrite
{
get
{
if (!IsWriting)
{
return true;
}
return IsWriting = false;
}
}
public override bool CanRead
{
get
{
if (!IsReading)
{
return true;
}
return IsReading = false;
}
}
public JsonInheritanceConverter(string discriminator, Type baseType)
: this(discriminator, baseType, null)
{
}
protected JsonInheritanceConverter(string discriminator, Type baseType, IReadOnlyDictionary<string, Type> subTypes = null)
{
this.discriminator = discriminator;
if (subTypes != null)
{
foreach (var subType in subTypes)
{
mapNameToType[subType.Value] = subType.Key;
mapTypeToName[subType.Key] = subType.Value;
}
}
else
{
foreach (var type in baseType.Assembly.GetTypes().Where(x => x != baseType && baseType.IsAssignableFrom(x)))
{
var name = type.GetTypeInfo().GetCustomAttribute<JsonSchemaAttribute>()?.Name ?? type.Name;
mapNameToType[type] = name;
mapTypeToName[name] = type;
}
}
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IsWriting = true;
try
{
var jsonObject = JObject.FromObject(value, serializer);
jsonObject.AddFirst(new JProperty(discriminator, mapNameToType[value.GetType()]));
writer.WriteToken(jsonObject.CreateReader());
}
finally
{
IsWriting = false;
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
IsReading = true;
try
{
var jsonObject = serializer.Deserialize<JObject>(reader);
var subName = jsonObject[discriminator]?.Value<string>();
if (subName == null)
{
return null;
}
if (!mapTypeToName.TryGetValue(subName, out var subType))
{
throw new InvalidOperationException($"Could not find subtype of '{objectType.Name}' with discriminator '{subName}'.");
}
return serializer.Deserialize(jsonObject.CreateReader(), subType);
}
finally
{
IsReading = false;
}
}
}
}

49
src/Squidex/Areas/Api/Controllers/MyJsonInheritanceConverter.cs

@ -0,0 +1,49 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschränkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using NJsonSchema.Converters;
namespace Squidex.Areas.Api.Controllers
{
public class MyJsonInheritanceConverter : JsonInheritanceConverter
{
private readonly IDictionary<string, Type> mapping;
private readonly Type baseType;
public MyJsonInheritanceConverter(string discriminator, Type baseType)
: base(baseType, discriminator)
{
this.baseType = baseType;
}
public MyJsonInheritanceConverter(string discriminator, Type baseType, IDictionary<string, Type> mapping)
: this(discriminator, baseType)
{
this.mapping = mapping;
}
public override string GetDiscriminatorValue(Type type)
{
var result = type.Name;
if (baseType != null)
{
var baseName = baseType.Name;
if (result.EndsWith(baseName, StringComparison.CurrentCulture))
{
return result.Substring(0, result.Length - baseName.Length);
}
}
return mapping?.FirstOrDefault(x => x.Value == type).Key ?? result;
}
}
}

6
src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleTriggerDtoFactory.cs

@ -28,14 +28,14 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Converters
public RuleTriggerDto Visit(AssetChangedTrigger trigger)
{
return SimpleMapper.Map(trigger, new AssetChangedTriggerDto());
return SimpleMapper.Map(trigger, new AssetChangedRuleTriggerDto());
}
public RuleTriggerDto Visit(ContentChangedTrigger trigger)
{
var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedTriggerSchemaDto())).ToArray();
var schemas = trigger.Schemas.Select(x => SimpleMapper.Map(x, new ContentChangedRuleTriggerSchemaDto())).ToArray();
return new ContentChangedTriggerDto { Schemas = schemas, HandleAll = trigger.HandleAll };
return new ContentChangedRuleTriggerDto { Schemas = schemas, HandleAll = trigger.HandleAll };
}
}
}

2
src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionProcessor.cs

@ -28,7 +28,7 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models
{
var discriminator = new OpenApiDiscriminator
{
JsonInheritanceConverter = new JsonInheritanceConverter("actionType", typeof(RuleAction)),
JsonInheritanceConverter = new MyJsonInheritanceConverter("actionType", typeof(RuleAction)),
PropertyName = "actionType"
};

2
src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionSerializer.cs

@ -11,7 +11,7 @@ using Squidex.Extensions.Actions;
namespace Squidex.Areas.Api.Controllers.Rules.Models
{
public sealed class RuleActionSerializer : JsonInheritanceConverter
public sealed class RuleActionSerializer : MyJsonInheritanceConverter
{
public RuleActionSerializer()
: base("actionType", typeof(RuleAction), RuleElementRegistry.Actions.ToDictionary(x => x.Key, x => x.Value.Type))

2
src/Squidex/Areas/Api/Controllers/Rules/Models/RuleTriggerDto.cs

@ -13,7 +13,7 @@ using Squidex.Domain.Apps.Core.Rules;
namespace Squidex.Areas.Api.Controllers.Rules.Models
{
[JsonConverter(typeof(JsonInheritanceConverter), "triggerType", typeof(RuleTriggerDto))]
[JsonConverter(typeof(MyJsonInheritanceConverter), "triggerType", typeof(RuleTriggerDto))]
[KnownType(nameof(Subtypes))]
public abstract class RuleTriggerDto
{

4
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/AssetChangedTriggerDto.cs → src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/AssetChangedRuleTriggerDto.cs

@ -5,15 +5,13 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
{
[JsonSchema("AssetChanged")]
public sealed class AssetChangedTriggerDto : RuleTriggerDto
public sealed class AssetChangedRuleTriggerDto : RuleTriggerDto
{
/// <summary>
/// Determines whether to handle the event when an asset is created.

6
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerDto.cs → src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerDto.cs

@ -7,7 +7,6 @@
using System.ComponentModel.DataAnnotations;
using System.Linq;
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Rules;
using Squidex.Domain.Apps.Core.Rules.Triggers;
using Squidex.Infrastructure.Collections;
@ -15,14 +14,13 @@ using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
{
[JsonSchema("ContentChanged")]
public sealed class ContentChangedTriggerDto : RuleTriggerDto
public sealed class ContentChangedRuleTriggerDto : RuleTriggerDto
{
/// <summary>
/// The schema settings.
/// </summary>
[Required]
public ContentChangedTriggerSchemaDto[] Schemas { get; set; }
public ContentChangedRuleTriggerSchemaDto[] Schemas { get; set; }
/// <summary>
/// Determines whether the trigger should handle all content changes events.

2
src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedTriggerSchemaDto.cs → src/Squidex/Areas/Api/Controllers/Rules/Models/Triggers/ContentChangedRuleTriggerSchemaDto.cs

@ -9,7 +9,7 @@ using System;
namespace Squidex.Areas.Api.Controllers.Rules.Models.Triggers
{
public sealed class ContentChangedTriggerSchemaDto
public sealed class ContentChangedRuleTriggerSchemaDto
{
/// <summary>
/// The id of the schema.

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/FieldPropertiesDto.cs

@ -14,7 +14,7 @@ using Squidex.Domain.Apps.Core.Schemas;
namespace Squidex.Areas.Api.Controllers.Schemas.Models
{
[JsonConverter(typeof(JsonInheritanceConverter), "fieldType", typeof(FieldPropertiesDto))]
[JsonConverter(typeof(MyJsonInheritanceConverter), "fieldType", typeof(FieldPropertiesDto))]
[KnownType(nameof(Subtypes))]
public abstract class FieldPropertiesDto
{

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ArrayFieldPropertiesDto.cs

@ -5,13 +5,11 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Array")]
public sealed class ArrayFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/AssetsFieldPropertiesDto.cs

@ -5,14 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Assets")]
public sealed class AssetsFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/BooleanFieldPropertiesDto.cs

@ -5,13 +5,11 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Boolean")]
public sealed class BooleanFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/DateTimeFieldPropertiesDto.cs

@ -5,14 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using NodaTime;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("DateTime")]
public sealed class DateTimeFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/GeolocationFieldPropertiesDto.cs

@ -5,13 +5,11 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Geolocation")]
public sealed class GeolocationFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/JsonFieldPropertiesDto.cs

@ -5,13 +5,11 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Json")]
public sealed class JsonFieldPropertiesDto : FieldPropertiesDto
{
public override FieldProperties ToProperties()

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/NumberFieldPropertiesDto.cs

@ -5,14 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Number")]
public sealed class NumberFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/ReferencesFieldPropertiesDto.cs

@ -6,13 +6,11 @@
// ==========================================================================
using System;
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("References")]
public sealed class ReferencesFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/StringFieldPropertiesDto.cs

@ -5,14 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("String")]
public sealed class StringFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/Models/Fields/TagsFieldPropertiesDto.cs

@ -5,14 +5,12 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using NJsonSchema.Annotations;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure.Collections;
using Squidex.Infrastructure.Reflection;
namespace Squidex.Areas.Api.Controllers.Schemas.Models.Fields
{
[JsonSchema("Tags")]
public sealed class TagsFieldPropertiesDto : FieldPropertiesDto
{
/// <summary>

2
src/Squidex/Areas/Api/Controllers/Schemas/SchemasController.cs

@ -69,7 +69,7 @@ namespace Squidex.Areas.Api.Controllers.Schemas
/// </returns>
[HttpGet]
[Route("apps/{app}/schemas/{name}/")]
[ProducesResponseType(typeof(SchemaDetailsDto[]), 200)]
[ProducesResponseType(typeof(SchemaDetailsDto), 200)]
[ApiPermission(Permissions.AppCommon)]
[ApiCosts(0)]
public async Task<IActionResult> GetSchema(string app, string name)

Loading…
Cancel
Save