Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto stash before merge of "develop" and "origin/develop" #26

Merged
merged 5 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions BO4E-dotnet.Encryption/Anonymizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using BO4E.BO;
using BO4E.Extensions.BusinessObjects;
using BO4E.meta;
using BO4E.meta.LenientParsing;
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
Expand Down
29 changes: 27 additions & 2 deletions BO4E-dotnet/BO/BusinessObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;

using BO4E.meta;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Schema.Generation;
using Newtonsoft.Json.Serialization;

using ProtoBuf;

namespace BO4E.BO
Expand Down Expand Up @@ -512,12 +515,34 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
throw new NotImplementedException($"The type '{jo["boTyp"].Value<string>()}' does not exist in the BO4E standard.");
}
}
return JsonConvert.DeserializeObject(jo.ToString(), boType);
var deserializationMethod = serializer.GetType() // https://stackoverflow.com/a/5218492/10009545
.GetMethods()
.Where(m => m.Name == nameof(serializer.Deserialize))
.Select(m => new
{
Method = m,
Params = m.GetParameters(),
Args = m.GetGenericArguments()
})
.Where(x => x.Params.Length == 1
&& x.Args.Length == 1)
.Select(x => x.Method)
.First()
.GetGenericMethodDefinition()
.MakeGenericMethod(new Type[] { boType });
try
{
return deserializationMethod.Invoke(serializer, new object[] { jo.CreateReader() });
}
catch (TargetInvocationException tie) when (tie.InnerException != null)
{
throw tie.InnerException; // to hide the reflection to the outside.
}
}
else
{
serializer.ContractResolver.ResolveContract(objectType).Converter = null;
return serializer.Deserialize(reader, objectType);
return serializer.Deserialize(JObject.Load(reader).CreateReader(), objectType);
}
}

Expand Down
2 changes: 1 addition & 1 deletion BO4E-dotnet/BO/Marktlokation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public class Marktlokation : BusinessObject
public Gasqualitaet? gasqualitaet;

/// <summary>Link zum Geschäftspartner, dem diese Marktlokation gehört.</summary>
[JsonProperty(Required = Required.Default, Order = 17)]
[JsonProperty(Required = Required.Default, Order = 17, NullValueHandling = NullValueHandling.Ignore)]
[ProtoMember(17)]
public Geschaeftspartner endkunde;

Expand Down
3 changes: 3 additions & 0 deletions BO4E-dotnet/BO/Rechnung.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Globalization;

using BO4E.COM;
using BO4E.ENUM;
using BO4E.meta;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using ProtoBuf;

namespace BO4E.BO
Expand Down
2 changes: 1 addition & 1 deletion BO4E-dotnet/BO/Zaehler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public class Zaehler : BusinessObject
public List<Zaehlwerk> zaehlwerke;

/// <summary>Der Hersteller des Zählers. Details <see cref="Geschaeftspartner" /></summary>
[JsonProperty(Required = Required.Default, Order = 13)]
[JsonProperty(Required = Required.Default, Order = 13, NullValueHandling =NullValueHandling.Ignore)]
[ProtoMember(13)]
public Geschaeftspartner zaehlerhersteller;

Expand Down
2 changes: 1 addition & 1 deletion BO4E-dotnet/BO4E-dotnet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile></DocumentationFile>
<Optimize>true</Optimize>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>DEBUG</DefineConstants>
Expand Down
199 changes: 10 additions & 189 deletions BO4E-dotnet/BoMapper.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

using BO4E.BO;
using BO4E.meta;
using BO4E.meta.LenientParsing;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Serialization;

namespace BO4E
{
/// <summary>
Expand Down Expand Up @@ -150,6 +151,9 @@ public static BusinessObject MapObject(Type businessObjectType, JObject jobject,
break;
case LenientParsing.Bo4eUri:
converters.Add(new LenientBo4eUriConverter());
break;
case LenientParsing.StringToInt:
converters.Add(new LenientStringToIntConverter());
break;
// case LenientParsing.EmptyLists:
// converters.Add(new LenientRequiredListConverter());
Expand Down Expand Up @@ -213,6 +217,9 @@ public static JsonSerializerSettings GetJsonSerializerSettings(HashSet<string> u
case LenientParsing.Bo4eUri:
converters.Add(new LenientBo4eUriConverter());
break;
case LenientParsing.StringToInt:
converters.Add(new LenientStringToIntConverter());
break;
// case LenientParsing.EmptyLists:
// converters.Add(new LenientRequiredListConverter());
// break;
Expand Down Expand Up @@ -403,192 +410,6 @@ public static FieldInfo[] GetAnnotatedFields(string boName, Type attributeType)
.ToArray<FieldInfo>();
}

private class LenientEnumListConverter : JsonConverter
{

public override bool CanConvert(Type objectType)
{
if (!objectType.IsGenericType)
{
return false;
}
if (objectType.GetGenericTypeDefinition() != typeof(List<>))
{
return false;
}
Type expectedListElementType = objectType.GetGenericArguments()[0];
return expectedListElementType.ToString().StartsWith("BO4E.ENUM");
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader); // https://stackoverflow.com/a/47864946/10009545
List<object> rawList = token.ToObject<List<object>>();
Type expectedListElementType = objectType.GetGenericArguments()[0];
Type expectedListType = typeof(List<>).MakeGenericType(expectedListElementType);
object result = Activator.CreateInstance(expectedListType);
if (rawList == null || rawList.Count == 0)
{
return result;
}
// First try to parse the List normally, in case it's formatted as expected
foreach (var rawItem in rawList)
{
if (rawItem.GetType() == typeof(string) && Enum.IsDefined(expectedListElementType, rawItem.ToString()))
{
// default. everything is as it should be :-)
object enumValue = Enum.Parse(expectedListElementType, rawItem.ToString());
((IList)result).Add(enumValue);
}
else if (rawItem.GetType() == typeof(JObject))
{
Dictionary<string, object> rawDict = ((JObject)rawItem).ToObject<Dictionary<string, object>>();
object rawObject = rawDict.Values.FirstOrDefault<object>();
object enumValue = Enum.Parse(expectedListElementType, rawObject.ToString());
((IList)result).Add(enumValue);
}
else
{
((IList)result).Add(rawItem);
}
}
return result;
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

/// <summary>
/// The lenient DateTimeConverter allows for transforming strings into (nullable) DateTime(?) objects,
/// even if their formatting is somehow weird.
/// </summary>
public class LenientDateTimeConverter : JsonConverter
{
// basic structure copied from https://stackoverflow.com/a/33172735/10009545

private readonly DateTime? _defaultDateTime;

public LenientDateTimeConverter(DateTime? defaultDateTime = null)
{
this._defaultDateTime = defaultDateTime;
}

public LenientDateTimeConverter() : this(null)
{

}

private readonly List<string> ALLOWED_DATETIME_FORMATS = new List<string>()
{
"yyyyMMddHHmm",
"yyyyMMddHHmmss",
@"yyyyMMddHHmmss'--T::zzzz'", // ToDo: remove again. this is just a buggy, nasty workaround
};

public override bool CanConvert(Type objectType)
{
return (objectType == typeof(DateTime) || objectType == typeof(DateTime?));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
string rawDate;
if (reader.Value == null)
{
return null;
}
else if (reader.Value as string != null)
{
rawDate = (string)reader.Value;
}
else if (reader.Value.GetType() == typeof(DateTime))
{
return (DateTime)reader.Value;
}
else
{
rawDate = reader.Value.ToString();
}
// First try to parse the date string as is (in case it is correctly formatted)
if (DateTime.TryParse(rawDate, out DateTime date))
{
return date;
}

foreach (string dtf in ALLOWED_DATETIME_FORMATS)
{
if (DateTime.TryParseExact(rawDate, dtf, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
}

// It's not a date after all, so just return the default value
if (objectType == typeof(DateTime?))
{
return null;
}
if (this._defaultDateTime.HasValue)
{
return _defaultDateTime;
}
else
{
throw new JsonReaderException($"Couldn't convert {rawDate} to any of the allowed date time formats: {String.Join(";", ALLOWED_DATETIME_FORMATS)})");
}
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

private class LenientBo4eUriConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Bo4eUri));
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
{
return null;
}
string rawString = (string)reader.Value;
if (rawString.Trim() == String.Empty)
{
return null;
}
return new Bo4eUri(rawString);
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

/// <summary>
/// The UserPropertiesContractResolver allows to put non-BO4E-standard/custom fields/properties into a "userProperties" object.
/// </summary>
Expand Down
Loading