diff --git a/BO4E.Extensions/BusinessObjects/Benachrichtigung/BenachrichtigungExtension.cs b/BO4E.Extensions/BusinessObjects/Benachrichtigung/BenachrichtigungExtension.cs
index d147b902..c35959c9 100644
--- a/BO4E.Extensions/BusinessObjects/Benachrichtigung/BenachrichtigungExtension.cs
+++ b/BO4E.Extensions/BusinessObjects/Benachrichtigung/BenachrichtigungExtension.cs
@@ -34,7 +34,11 @@ public static bool Has(this BO.Benachrichtigung b, string key, string value)
///
public static bool Has(this BO.Benachrichtigung b, GenericStringStringInfo gssi)
{
- if (b.Infos == null || b.Infos.Count == 0) return false;
+ if (b.Infos == null || b.Infos.Count == 0)
+ {
+ return false;
+ }
+
// ToDo für Hamid: Bitte prüfen, warum Contains false zurückliefert.
return b.Infos.Any(m => m.KeyColumn == gssi.KeyColumn && m.Value == gssi.Value);
}
@@ -47,7 +51,11 @@ public static bool Has(this BO.Benachrichtigung b, GenericStringStringInfo gssi)
/// true if key is in
public static bool Has(this BO.Benachrichtigung b, string key)
{
- if (b.Infos == null || b.Infos.Count == 0) return false;
+ if (b.Infos == null || b.Infos.Count == 0)
+ {
+ return false;
+ }
+
return b.Infos.Any(gssi => gssi.KeyColumn == key);
}
@@ -68,11 +76,18 @@ public static bool Has(this BO.Benachrichtigung b, string key)
public static bool Has(this BO.Benachrichtigung b, string keyName, Predicate predicate,
bool passByDefault = true, TypeConverter typeConverter = null) where T : IComparable
{
- if (!b.Has(keyName)) return passByDefault;
+ if (!b.Has(keyName))
+ {
+ return passByDefault;
+ }
+
foreach (var info in b.Infos.Where(gssi => gssi.KeyColumn == keyName))
try
{
- if (typeConverter == null) typeConverter = TypeDescriptor.GetConverter(typeof(T));
+ if (typeConverter == null)
+ {
+ typeConverter = TypeDescriptor.GetConverter(typeof(T));
+ }
{
var value = (T)typeConverter.ConvertFromString(info.Value);
@@ -97,11 +112,18 @@ public static void MoveInfosToUserProperties(this BO.Benachrichtigung b, bool ov
{
if (b.Infos != null && b.Infos.Count > 0)
{
- if (b.UserProperties == null) b.UserProperties = new Dictionary();
+ if (b.UserProperties == null)
+ {
+ b.UserProperties = new Dictionary();
+ }
+
foreach (var info in b.Infos)
{
if (b.UserProperties.ContainsKey(info.KeyColumn) && overwriteExistingKeys)
+ {
b.UserProperties.Remove(info.KeyColumn);
+ }
+
b.UserProperties.Add(info.KeyColumn,
info.Value); // might throw exception if key exists and !overwriteExistingKeys. That's ok.
}
diff --git a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtension.cs b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtension.cs
index f4f35217..2c256b02 100644
--- a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtension.cs
+++ b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtension.cs
@@ -115,12 +115,23 @@ public static decimal GetTotalConsumption(this BO.Energiemenge em,
/// Tuple of consumption value and automatically determined unit of measurement
public static Tuple GetConsumption(this BO.Energiemenge em, ITimeRange reference)
{
- if (!IsPure(em)) throw new ArgumentException("The Energiemenge is not pure.");
- if (em.Energieverbrauch.Count == 0) return Tuple.Create(0.0M, Mengeneinheit.ANZAHL);
+ if (!IsPure(em))
+ {
+ throw new ArgumentException("The Energiemenge is not pure.");
+ }
+
+ if (em.Energieverbrauch.Count == 0)
+ {
+ return Tuple.Create(0.0M, Mengeneinheit.ANZAHL);
+ }
+
ISet einheiten = new HashSet(em.Energieverbrauch.Select(x => x.Einheit));
if (einheiten.Count > 1)
- // z.B. kWh und Wh oder Monat und Jahr... Die liefern IsPure==true.
+ // z.B. kWh und Wh oder Monat und Jahr... Die liefern IsPure==true.
+ {
throw new NotImplementedException("Converting different units of same type is not supported yet.");
+ }
+
var v = em.Energieverbrauch.First();
var consumption = em.GetConsumption(reference, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit);
return Tuple.Create(consumption, v.Einheit);
@@ -143,8 +154,11 @@ public static decimal GetConsumption(this BO.Energiemenge em, ITimeRange referen
Wertermittlungsverfahren? wev, string obiskennzahl, Mengeneinheit me)
{
if (!me.IsExtensive())
+ {
throw new ArgumentException(
$"The Mengeneinheit {me} isn't extensive. Calculating a consumption doesn't make sense.");
+ }
+
return em.Energieverbrauch
.Where(v => v.Wertermittlungsverfahren == wev && v.Obiskennzahl == obiskennzahl && v.Einheit == me)
.Sum(v => GetOverlapFactor(new TimeRange((v.Startdatum ?? DateTimeOffset.MinValue).DateTime, (v.Enddatum ?? DateTimeOffset.MinValue).DateTime), reference, false) * v.Wert);
@@ -166,9 +180,13 @@ public static BO.Energiemenge Normalise(this BO.Energiemenge em, decimal target
totalConsumption = em.GetTotalConsumption();
result = em.DeepClone();
if (totalConsumption.Item1 != 0.0M)
+ {
scalingFactor = target / totalConsumption.Item1;
+ }
else
+ {
scalingFactor = 0.0M;
+ }
Parallel.ForEach(result.Energieverbrauch.Where(v => v.Einheit == totalConsumption.Item2),
v => { v.Wert = scalingFactor * v.Wert; });
@@ -188,14 +206,22 @@ public static BO.Energiemenge Normalise(this BO.Energiemenge em, decimal target
public static decimal? GetLoad(this BO.Energiemenge em, Mengeneinheit me, DateTime dt)
{
if (!me.IsIntensive())
+ {
throw new ArgumentException(
$"The Mengeneinheit {me} isn't intensive. Calculating the value for a specific point in time doesn't make sense.");
+ }
+
decimal? result = null;
foreach (var v in em.Energieverbrauch.Where(v => v.Startdatum <= dt && dt < v.Enddatum))
if (result.HasValue)
+ {
result += v.Wert;
+ }
else
+ {
result = v.Wert;
+ }
+
return result;
}
@@ -209,9 +235,16 @@ public static BO.Energiemenge Normalise(this BO.Energiemenge em, decimal target
/// Tuple of average value and unit of measurement
public static Tuple GetAverage(this BO.Energiemenge em)
{
- if (!IsPure(em)) throw new ArgumentException("Energiemenge is not pure.");
+ if (!IsPure(em))
+ {
+ throw new ArgumentException("Energiemenge is not pure.");
+ }
+
+ if (em.Energieverbrauch.Count == 0)
+ {
+ return Tuple.Create(null, Mengeneinheit.KW);
+ }
- if (em.Energieverbrauch.Count == 0) return Tuple.Create(null, Mengeneinheit.KW);
var v = em.Energieverbrauch.First();
return Tuple.Create(em.GetAverage(v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit), v.Einheit);
}
@@ -251,13 +284,21 @@ public static BO.Energiemenge Normalise(this BO.Energiemenge em, decimal target
{
var overlapFactor = GetOverlapFactor(new TimeRange((v.Startdatum ?? DateTimeOffset.MinValue).DateTime, (v.Enddatum ?? DateTimeOffset.MinValue).DateTime), reference, true);
if (result.HasValue)
+ {
result += overlapFactor * v.Wert;
+ }
else
+ {
result = v.Wert;
+ }
+
overallDenominator += overlapFactor;
}
- if (result.HasValue) return result / overallDenominator;
+ if (result.HasValue)
+ {
+ return result / overallDenominator;
+ }
return null;
}
@@ -293,16 +334,25 @@ public static List GetMissingTimeRanges(this BO.Energiemenge em, ITim
if (filteredVerbrauch.Count < 2)
+ {
throw new ArgumentException("Not enough entries in energieverbrauch to determine periodicity.");
+ }
+
if (!IsEvenlySpaced(em, reference, wev, obis, me, true))
+ {
throw new ArgumentException(
"The provided Energiemenge is not evenly spaced although gaps are allowed.");
+ }
+
var periodicity = GetTimeSpans(em, wev, obis, me).Min();
if (
Math.Abs((reference.Start - em.GetMinDate()).TotalMilliseconds % periodicity.TotalMilliseconds) !=
0)
+ {
throw new ArgumentException(
$"The absolute difference between reference.start ({reference.Start}) and the minimal date time in the Energiemenge ({em.GetMinDate()}) has to be an integer multiple of the periodicity {periodicity.TotalMilliseconds} but was {(reference.Start - em.GetMinDate()).TotalMilliseconds}.");
+ }
+
// since it's assured, that the energieverbrauch entries are evenly spaced it doesn't matter which entry we use to determine the duration.
var duration = filteredVerbrauch.Values.Min(v => v.Enddatum) -
filteredVerbrauch.Values.Min(v => v.Startdatum);
@@ -327,7 +377,9 @@ public static List GetMissingTimeRanges(this BO.Energiemenge em, ITim
if (!filteredVerbrauch.ContainsKey(
new Tuple(dt,
dt + duration))) // Where(v => v.startdatum == dt && v.enddatum == dt + duration).Any())
+ {
result.Add(new TimeRange(dt, (dt + duration).Value));
+ }
//}
}
@@ -345,8 +397,11 @@ public static List GetMissingTimeRanges(this BO.Energiemenge em, ITim
public static List GetMissingTimeRanges(this BO.Energiemenge em, TimeRange reference)
{
if (!em.IsPure())
+ {
throw new ArgumentException(
"The Energiemenge you provided is not pure. Consider using the overloaded method.");
+ }
+
var v = em.Energieverbrauch.FirstOrDefault();
return GetMissingTimeRanges(em, reference, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit);
}
@@ -372,7 +427,11 @@ public static bool IsEvenlySpaced(this BO.Energiemenge em, ITimeRange reference,
startEndDatumPeriods = GetTimeSpans(em, wev, obis, me);
- if (startEndDatumPeriods.Count < 2) return true;
+ if (startEndDatumPeriods.Count < 2)
+ {
+ return true;
+ }
+
if (allowGaps)
{
// each time difference must be a multiple of the smallest difference.
@@ -380,9 +439,11 @@ public static bool IsEvenlySpaced(this BO.Energiemenge em, ITimeRange reference,
var minDiff = startEndDatumPeriods.Min().TotalSeconds;
foreach (var ts in startEndDatumPeriods)
if (Math.Abs(ts.TotalSeconds % minDiff) != 0)
- // use profiler as logger:
+ // use profiler as logger:
+ {
return false;
+ }
return true;
@@ -408,7 +469,9 @@ public static bool IsEvenlySpaced(this BO.Energiemenge em, bool allowGaps = fals
var combinations = GetWevObisMeCombinations(em);
foreach (var combo in combinations)
if (!em.IsEvenlySpaced(em.GetTimeRange(), combo.Item1, combo.Item2, combo.Item3, allowGaps))
+ {
return false;
+ }
return true;
@@ -490,8 +553,15 @@ public static decimal GetCoverage(this BO.Energiemenge em, ITimeRange reference)
{
if (!IsPure(em))
+ {
throw new ArgumentException("The Energiemenge is not pure. Cannot determine parameters.");
- if (em.Energieverbrauch.Count == 0) return 0.0M;
+ }
+
+ if (em.Energieverbrauch.Count == 0)
+ {
+ return 0.0M;
+ }
+
var v = em.Energieverbrauch.First();
return em.GetCoverage(reference, v.Wertermittlungsverfahren, v.Obiskennzahl, v.Einheit);
@@ -571,8 +641,10 @@ private static decimal GetOverlapFactor(TimeRange period, ITimeRange reference,
try
{
if (toReference)
+ {
return (decimal)intersectedPeriods.TotalDuration.TotalSeconds /
(decimal)reference.Duration.TotalSeconds;
+ }
return (decimal)intersectedPeriods.TotalDuration.TotalSeconds / (decimal)period.Duration.TotalSeconds;
}
@@ -653,8 +725,14 @@ public static bool IsPureUserProperties(this BO.Energiemenge em)
if (values.TryGetValue(key, out var onlyValue))
{
if (rawValue == null && onlyValue != null)
+ {
return false;
- if (rawValue != null && !rawValue.Equals(onlyValue)) return false;
+ }
+
+ if (rawValue != null && !rawValue.Equals(onlyValue))
+ {
+ return false;
+ }
}
else
{
@@ -674,7 +752,10 @@ public static bool IsPureUserProperties(this BO.Energiemenge em)
public static bool IsPureMengeneinheit(this BO.Energiemenge em)
{
- if (em.Energieverbrauch.Select(v => v.Einheit).Distinct().Count() <= 1) return true;
+ if (em.Energieverbrauch.Select(v => v.Einheit).Distinct().Count() <= 1)
+ {
+ return true;
+ }
var me1 = em.Energieverbrauch.Select(v => v.Einheit).First();
return em.Energieverbrauch.Select(v => v.Einheit).All(me2 => me1.IsConvertibleTo(me2));
@@ -712,7 +793,10 @@ public static bool IsExtensive(this BO.Energiemenge em)
/// a list of pure energiemengen ()
public static List SplitInPureGroups(this BO.Energiemenge em)
{
- if (em.Energieverbrauch == null) return new List { em };
+ if (em.Energieverbrauch == null)
+ {
+ return new List { em };
+ }
var result = new List();
foreach (var group in em.Energieverbrauch.GroupBy(PurityGrouper))
@@ -732,7 +816,10 @@ public static bool IsExtensive(this BO.Energiemenge em)
///
public static void Detangle(this BO.Energiemenge em)
{
- if (em.Energieverbrauch != null) em.Energieverbrauch = VerbrauchExtension.Detangle(em.Energieverbrauch);
+ if (em.Energieverbrauch != null)
+ {
+ em.Energieverbrauch = VerbrauchExtension.Detangle(em.Energieverbrauch);
+ }
}
private class BasicVerbrauchDateTimeComparer : IComparer
diff --git a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionCompleteness.cs b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionCompleteness.cs
index 63d3268d..95c5310d 100644
--- a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionCompleteness.cs
+++ b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionCompleteness.cs
@@ -135,10 +135,15 @@ public static CompletenessReport GetCompletenessReport(this BO.Energiemenge em,
em.Energieverbrauch.Select(v => new TimeRange((v.Startdatum ?? DateTimeOffset.MinValue).DateTime, (v.Enddatum ?? DateTimeOffset.MinValue).DateTime)));
ITimeRange limits;
if (result.ReferenceTimeFrame != null && result.ReferenceTimeFrame.Startdatum.HasValue)
+ {
limits = new TimeRange(result.ReferenceTimeFrame.Startdatum.Value.UtcDateTime,
result.ReferenceTimeFrame.Enddatum.Value.UtcDateTime);
+ }
else
+ {
limits = null;
+ }
+
var gaps = new TimeGapCalculator().GetGaps(nonNullValues, limits);
result.Gaps = gaps.Select(gap => new CompletenessReport.BasicVerbrauch
{
@@ -153,20 +158,28 @@ public static CompletenessReport GetCompletenessReport(this BO.Energiemenge em,
result.values.Sort(new BasicVerbrauchDateTimeComparer());
}*/
if (em.IsPure(true))
+ {
try
{
foreach (var kvp in em.Energieverbrauch.Where(v => v.UserProperties != null)
- .SelectMany(v => v.UserProperties))
+ .SelectMany(v => v.UserProperties))
{
- if (result.UserProperties == null) result.UserProperties = new Dictionary();
+ if (result.UserProperties == null)
+ {
+ result.UserProperties = new Dictionary();
+ }
+
if (!result.UserProperties.ContainsKey(kvp.Key))
+ {
result.UserProperties.Add(kvp.Key, kvp.Value);
+ }
}
}
catch (InvalidOperationException)
{
// ok, there's no Verbrauch with user properties.
}
+ }
}
/*else
@@ -190,8 +203,11 @@ public static CompletenessReport GetCompletenessReport(this BO.Energiemenge em,
public static CompletenessReport GetCompletenessReport(this BO.Energiemenge em)
{
if (!em.IsPure())
+ {
throw new ArgumentException(
"The provided Energiemenge is not pure. Please use overloaded method GetCompletenessReport(... , wertermittlungsverfahren, obiskennzahl, mengeneinheit).");
+ }
+
Verbrauch v;
try
{
@@ -220,11 +236,17 @@ public static CompletenessReport GetCompletenessReport(this BO.Energiemenge em)
public static IDictionary GetSlicedCompletenessReports(this BO.Energiemenge em,
IEnumerable ranges, bool useParallelExecution = false)
{
- if (ranges == null) throw new ArgumentNullException(nameof(ranges), "list of time ranges must not be null");
+ if (ranges == null)
+ {
+ throw new ArgumentNullException(nameof(ranges), "list of time ranges must not be null");
+ }
+
if (ranges.Any())
{
if (useParallelExecution)
+ {
return ranges.AsParallel().ToDictionary(r => r, r => GetCompletenessReport(em, r));
+ }
return ranges.ToDictionary(r => r, r => GetCompletenessReport(em, r));
}
diff --git a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionPlausibility.cs b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionPlausibility.cs
index c8568c41..de575bc6 100644
--- a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionPlausibility.cs
+++ b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionPlausibility.cs
@@ -42,10 +42,15 @@ public static PlausibilityReport GetPlausibilityReport(this BO.Energiemenge emRe
{
var overlap = trReference.GetIntersection(trOther);
if (!ignoreLocation)
+ {
if (!(emReference.LokationsId == emOther.LokationsId &&
emReference.LokationsTyp == emOther.LokationsTyp))
+ {
throw new ArgumentException(
$"locations do not match! '{emReference.LokationsId}' ({emReference.LokationsTyp}) != '{emOther.LokationsId}' ({emOther.LokationsTyp})");
+ }
+ }
+
timeframe = overlap;
}
@@ -59,13 +64,17 @@ public static PlausibilityReport GetPlausibilityReport(this BO.Energiemenge emRe
{
// unit mismatch
if (consumptionReference.Item2.IsConvertibleTo(consumptionOtherRaw.Item2))
+ {
consumptionOther = new Tuple(
consumptionOtherRaw.Item1 *
consumptionOtherRaw.Item2.GetConversionFactor(consumptionReference.Item2),
consumptionReference.Item2);
+ }
else
+ {
throw new ArgumentException(
$"The unit {consumptionOtherRaw.Item2} is not comparable to {consumptionReference.Item2}!");
+ }
}
else
{
@@ -111,9 +120,14 @@ public static PlausibilityReport GetPlausibilityReport(this BO.Energiemenge emRe
AbsoluteDeviationEinheit = consumptionReference.Item2
};
if (relativeDeviation.HasValue)
+ {
pr.RelativeDeviation = Math.Round(relativeDeviation.Value, 4);
+ }
else
+ {
pr.RelativeDeviation = null;
+ }
+
return pr;
}
@@ -144,7 +158,11 @@ public static PlausibilityReport GetPlausibilityReport(this BO.Energiemenge ener
public static IDictionary GetSlicedPlausibilityReports(this BO.Energiemenge em,
PlausibilityReportConfiguration config, IEnumerable ranges)
{
- if (ranges == null) throw new ArgumentNullException(nameof(ranges), "list of time ranges must not be null");
+ if (ranges == null)
+ {
+ throw new ArgumentNullException(nameof(ranges), "list of time ranges must not be null");
+ }
+
var result = new Dictionary();
foreach (var range in ranges)
{
@@ -175,8 +193,16 @@ public static IDictionary GetSlicedPlausibilityR
public static IDictionary GetDailyPlausibilityReports(this BO.Energiemenge em,
PlausibilityReportConfiguration config)
{
- if (config == null) throw new ArgumentNullException(nameof(config));
- if (config.Timeframe == null) throw new ArgumentNullException(nameof(config.Timeframe));
+ if (config == null)
+ {
+ throw new ArgumentNullException(nameof(config));
+ }
+
+ if (config.Timeframe == null)
+ {
+ throw new ArgumentNullException(nameof(config.Timeframe));
+ }
+
var slices = GetLocalDailySlices(new TimeRange
{
Start = config.Timeframe.Startdatum.Value.UtcDateTime,
@@ -197,8 +223,16 @@ public static IDictionary GetDailyPlausibilityRe
public static IDictionary GetMonthlyPlausibilityReports(this BO.Energiemenge em,
PlausibilityReportConfiguration config)
{
- if (config == null) throw new ArgumentNullException(nameof(config));
- if (config.Timeframe == null) throw new ArgumentNullException(nameof(config.Timeframe));
+ if (config == null)
+ {
+ throw new ArgumentNullException(nameof(config));
+ }
+
+ if (config.Timeframe == null)
+ {
+ throw new ArgumentNullException(nameof(config.Timeframe));
+ }
+
var slices = GetLocalMonthlySlices(new TimeRange
{
Start = config.Timeframe.Startdatum.Value.UtcDateTime,
diff --git a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionSlicingHelper.cs b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionSlicingHelper.cs
index a09ed57c..9128389f 100644
--- a/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionSlicingHelper.cs
+++ b/BO4E.Extensions/BusinessObjects/Energiemenge/EnergiemengeExtensionSlicingHelper.cs
@@ -12,14 +12,26 @@ public static partial class EnergiemengeExtension
internal static IList GetLocalDailySlices(ITimeRange overallTimeRange, TimeZoneInfo tz = null)
{
if (overallTimeRange == null)
+ {
throw new ArgumentNullException(nameof(overallTimeRange), "overall time range must not be null");
- if (tz == null) tz = CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo;
+ }
+
+ if (tz == null)
+ {
+ tz = CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo;
+ }
+
if (overallTimeRange.Start.Kind == DateTimeKind.Unspecified)
+ {
throw new ArgumentException("TimeRange start must not have DateTimeKind.Unspecified",
nameof(overallTimeRange));
+ }
+
if (overallTimeRange.End.Kind == DateTimeKind.Unspecified)
+ {
throw new ArgumentException("TimeRange end must not have DateTimeKind.Unspecified",
nameof(overallTimeRange));
+ }
IList result = new List();
if (!overallTimeRange.IsMoment)
@@ -43,7 +55,10 @@ internal static IList GetLocalDailySlices(ITimeRange overallTimeRang
internal static IList GetLocalMonthlySlices(ITimeRange overallTimeRange, TimeZoneInfo tz = null)
{
if (overallTimeRange == null)
+ {
throw new ArgumentNullException(nameof(overallTimeRange), "overall time range must not be null");
+ }
+
DateTime localStart;
DateTime localEnd;
if (tz == null)
@@ -51,13 +66,19 @@ internal static IList GetLocalMonthlySlices(ITimeRange overallTimeRa
tz = CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo;
if (overallTimeRange.Start.Kind != DateTimeKind.Utc)
+ {
throw new ArgumentException(
$"TimeRange start must have DateTimeKind.Utc if no timezone is given in parameter {nameof(tz)}",
nameof(overallTimeRange));
+ }
+
if (overallTimeRange.End.Kind != DateTimeKind.Utc)
+ {
throw new ArgumentException(
$"TimeRange end must have DateTimeKind.Utc if no timezone is given in parameter {nameof(tz)}",
nameof(overallTimeRange));
+ }
+
localStart = TimeZoneInfo.ConvertTimeFromUtc(overallTimeRange.Start, tz);
localEnd = TimeZoneInfo.ConvertTimeFromUtc(overallTimeRange.End, tz);
}
@@ -142,7 +163,11 @@ internal static IList GetLocalMonthlySlices(ITimeRange overallTimeRa
///
public static DateTime AddDaysDST(this DateTime dt, double value, TimeZoneInfo tz = null)
{
- if (tz == null) tz = CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo;
+ if (tz == null)
+ {
+ tz = CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo;
+ }
+
switch (dt.Kind)
{
case DateTimeKind.Local:
diff --git a/BO4E.Extensions/COM/VerbrauchExtension.cs b/BO4E.Extensions/COM/VerbrauchExtension.cs
index 57de3079..9100e8c8 100644
--- a/BO4E.Extensions/COM/VerbrauchExtension.cs
+++ b/BO4E.Extensions/COM/VerbrauchExtension.cs
@@ -88,9 +88,13 @@ public static HashSet Merge(this Verbrauch v1, Verbrauch v2, bool red
vmerge.Enddatum = v1.Enddatum;
if (exclusiveV1Wert == 0.0M && exclusiveV2Wert == 0.0M &&
overlapV1Wert == overlapV2Wert)
+ {
vmerge.Wert = overlapV1Wert;
+ }
else
+ {
vmerge.Wert = v1.Wert - overlapV2Wert; // overlapV1Wert;
+ }
}
else
{
@@ -130,8 +134,11 @@ public static HashSet Merge(this Verbrauch v1, Verbrauch v2, bool red
if (redundant)
{
if (v1.Wert != v2.Wert)
+ {
throw new ArgumentException(
$"Data cannot be redundant if values ({v1.Wert}{v1.Einheit} vs. {v2.Wert}{v2.Einheit}) don't match for interval [{vmerge2.Startdatum}, {vmerge2.Enddatum}).");
+ }
+
vmerge2.Wert = v1.Wert;
}
else
@@ -269,8 +276,11 @@ public static List Detangle(IEnumerable input)
foreach (var frv in fullyRedundantVerbrauchs)
{
if (frv.av.x.Wert + frv.av.y.Wert != frv.z.Wert)
+ {
throw new ArgumentException(
$"Inconsistent data detected: {JsonConvert.SerializeObject(frv.av.x)} + {JsonConvert.SerializeObject(frv.av.y)} ≠ {JsonConvert.SerializeObject(frv.z)}");
+ }
+
subResult.Remove(frv.z);
}
@@ -406,9 +416,16 @@ public class VerbrauchDateTimeComparer : IComparer
{
int IComparer.Compare(Verbrauch x, Verbrauch y)
{
- if (x.Startdatum != y.Startdatum) return DateTimeOffset.Compare(x.Startdatum ?? DateTimeOffset.MinValue, y.Startdatum ?? DateTimeOffset.MinValue);
+ if (x.Startdatum != y.Startdatum)
+ {
+ return DateTimeOffset.Compare(x.Startdatum ?? DateTimeOffset.MinValue, y.Startdatum ?? DateTimeOffset.MinValue);
+ }
+
+ if (x.Enddatum != y.Enddatum)
+ {
+ return DateTimeOffset.Compare(x.Enddatum ?? DateTimeOffset.MinValue, y.Enddatum ?? DateTimeOffset.MinValue);
+ }
- if (x.Enddatum != y.Enddatum) return DateTimeOffset.Compare(x.Enddatum ?? DateTimeOffset.MinValue, y.Enddatum ?? DateTimeOffset.MinValue);
return 0;
}
}
diff --git a/BO4E.Extensions/ENUM/MengeneinheitExtension.cs b/BO4E.Extensions/ENUM/MengeneinheitExtension.cs
index 0b0ba32c..e620ba97 100644
--- a/BO4E.Extensions/ENUM/MengeneinheitExtension.cs
+++ b/BO4E.Extensions/ENUM/MengeneinheitExtension.cs
@@ -36,7 +36,10 @@ public static class MengeneinheitExtenion
public static bool AreConvertible(Mengeneinheit me1, Mengeneinheit me2)
{
#pragma warning disable 618
- if (me1 == Mengeneinheit.ZERO || me2 == Mengeneinheit.ZERO) return false;
+ if (me1 == Mengeneinheit.ZERO || me2 == Mengeneinheit.ZERO)
+ {
+ return false;
+ }
#pragma warning restore 618
return DimensionSets.Any(einheitengroup => einheitengroup.Contains(me1) && einheitengroup.Contains(me2));
}
@@ -109,13 +112,25 @@ public static decimal GetConversionFactor(this Mengeneinheit me1, Mengeneinheit
#pragma warning disable 618
if (me1 == Mengeneinheit.ZERO || me2 == Mengeneinheit.ZERO)
#pragma warning restore 618
+ {
throw new InvalidOperationException("You must not use the artificial 'ZERO' value.");
+ }
+
+ if (me1 == me2)
+ {
+ return 1.0M;
+ }
- if (me1 == me2) return 1.0M;
if (!me1.IsConvertibleTo(me2))
+ {
throw new InvalidOperationException(
$"{me1} and {me2} are not convertible into each other because they don't share the same dimension.");
- if ((int)me1 % (int)me2 == 0 || (int)me2 % (int)me2 == 0) return (decimal)me1 / (decimal)me2;
+ }
+
+ if ((int)me1 % (int)me2 == 0 || (int)me2 % (int)me2 == 0)
+ {
+ return (decimal)me1 / (decimal)me2;
+ }
throw new InvalidOperationException($"{me1} and {me2} are not (trivially) convertible into each other.");
}
diff --git a/BO4E.Reporting/CompletenessReport.cs b/BO4E.Reporting/CompletenessReport.cs
index 39d64416..1fd1ec7a 100644
--- a/BO4E.Reporting/CompletenessReport.cs
+++ b/BO4E.Reporting/CompletenessReport.cs
@@ -92,15 +92,33 @@ public class CompletenessReport : Report, IComparable
///
public int CompareTo(CompletenessReport other)
{
- if (ReferenceTimeFrame == null && other.ReferenceTimeFrame == null) return 0;
- if (ReferenceTimeFrame != null && other.ReferenceTimeFrame == null) return 1;
- if (ReferenceTimeFrame == null && other.ReferenceTimeFrame != null) return -1;
+ if (ReferenceTimeFrame == null && other.ReferenceTimeFrame == null)
+ {
+ return 0;
+ }
+
+ if (ReferenceTimeFrame != null && other.ReferenceTimeFrame == null)
+ {
+ return 1;
+ }
+
+ if (ReferenceTimeFrame == null && other.ReferenceTimeFrame != null)
+ {
+ return -1;
+ }
+
if (ReferenceTimeFrame != null && other.ReferenceTimeFrame != null)
{
if (ReferenceTimeFrame.Startdatum.HasValue && other.ReferenceTimeFrame.Startdatum.HasValue)
+ {
return Comparer.Default.Compare(ReferenceTimeFrame.Startdatum.Value,
other.ReferenceTimeFrame.Startdatum.Value);
- if (ReferenceTimeFrame.Startdatum.HasValue) return 1;
+ }
+
+ if (ReferenceTimeFrame.Startdatum.HasValue)
+ {
+ return 1;
+ }
return -1;
}
@@ -166,14 +184,23 @@ public int CompareTo(CompletenessReport other)
columns.Add("MSB"); // MSB
if (UserProperties.TryGetValue("profil", out var profil))
+ {
columns.Add(profil.ToString());
+ }
else
+ {
columns.Add(string.Empty);
+ }
if (UserProperties.TryGetValue("profilRolle", out var profilRolle))
+ {
columns.Add(profilRolle.ToString());
+ }
else
+ {
columns.Add(string.Empty);
+ }
+
if (Gaps != null && Gaps.Any())
{
var minGap = Gaps.Min(x => x.Startdatum); // OrderBy(x => x.Startdatum).First().Startdatum;
@@ -191,9 +218,14 @@ public int CompareTo(CompletenessReport other)
}
if (Coverage.HasValue)
+ {
columns.Add((Coverage.Value * 100).ToString("0.####") + " %");
+ }
else
+ {
columns.Add(string.Empty);
+ }
+
columns.Add("Status");
builder.Append(string.Join(separator, columns) + lineTerminator);
diff --git a/BO4E.Reporting/Report.cs b/BO4E.Reporting/Report.cs
index c98d563f..16eadf94 100644
--- a/BO4E.Reporting/Report.cs
+++ b/BO4E.Reporting/Report.cs
@@ -110,8 +110,11 @@ public abstract class Report : BusinessObject
}
if (i == 0 && headerLine)
+ {
resultBuilder = new StringBuilder(string.Join(separator.ToString(), sortedHeaderNamesList) +
lineTerminator);
+ }
+
resultBuilder.Append(string.Join(separator.ToString(), sortedResults) + lineTerminator);
}
}
@@ -156,8 +159,11 @@ public abstract class Report : BusinessObject
}
if (headerLine)
+ {
resultBuilder =
new StringBuilder(string.Join(separator.ToString(), sortedHeaderNamesList) + lineTerminator);
+ }
+
resultBuilder.Append(string.Join(separator.ToString(), sortedResults));
}
@@ -226,17 +232,25 @@ private Dictionary, List> Detect(Type type, char separator,
if (nestedValue != null)
{
var muterType = "";
- if (field.DeclaringType.BaseType == typeof(COM.COM)) muterType = field.DeclaringType.Name + ".";
+ if (field.DeclaringType.BaseType == typeof(COM.COM))
+ {
+ muterType = field.DeclaringType.Name + ".";
+ }
+
var val = nestedValue.ToString();
if (field.PropertyType == typeof(DateTime?))
{
if (((DateTime?)nestedValue).HasValue)
+ {
val = ((DateTime?)nestedValue).Value.ToString("yyyy-MM-ddTHH:mm:ssZ");
+ }
}
else if (field.PropertyType == typeof(DateTimeOffset?))
{
if (((DateTimeOffset?)nestedValue).HasValue)
+ {
val = ((DateTimeOffset?)nestedValue).Value.ToString("yyyy-MM-ddTHH:mm:ssZ");
+ }
}
else if (field.PropertyType == typeof(DateTime))
{
@@ -263,7 +277,10 @@ private Dictionary, List> DetectGaps(Type type, char separa
var h = returnData.Keys.First();
foreach (var field in fields)
{
- if (field.FieldType.IsSubclassOf(typeof(COM.COM))) continue;
+ if (field.FieldType.IsSubclassOf(typeof(COM.COM)))
+ {
+ continue;
+ }
if (field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(List<>))
{
@@ -280,7 +297,11 @@ private Dictionary, List> DetectGaps(Type type, char separa
var nestedValue = field.GetValue(value);
if (nestedValue != null)
{
- if (field.DeclaringType.BaseType == typeof(COM.COM)) continue;
+ if (field.DeclaringType.BaseType == typeof(COM.COM))
+ {
+ continue;
+ }
+
if (field.DeclaringType == typeof(BasicVerbrauch))
{
var muterType = "gap.";
@@ -288,7 +309,10 @@ private Dictionary, List> DetectGaps(Type type, char separa
if (field.FieldType == typeof(DateTime?))
{
if (((DateTime?)nestedValue).HasValue)
+ {
val = ((DateTime?)nestedValue).Value.ToString("yyyy-MM-ddTHH:mm:ssZ");
+ }
+
h.Add(muterType + field.Name);
d.Add(val.Contains(separator) ? "\"" + val + "\"" : val);
}
diff --git a/BO4E/BO/Avis.cs b/BO4E/BO/Avis.cs
index 41d33e58..da866e8e 100644
--- a/BO4E/BO/Avis.cs
+++ b/BO4E/BO/Avis.cs
@@ -1,3 +1,4 @@
+#nullable enable
using BO4E.COM;
using BO4E.ENUM;
using BO4E.meta;
@@ -20,37 +21,37 @@ public class Avis : BusinessObject
///
/// Eine im Verwendungskontext eindeutige Nummer für das Avis.
///
- [JsonProperty(PropertyName = "avisNummer", Required = Required.Always)]
+ [JsonProperty(PropertyName = "avisNummer", Required = Required.Default)]
[JsonPropertyName("avisNummer")]
[NonOfficial(NonOfficialCategory.MISSING)]
[ProtoMember(1000)]
- public string AvisNummer { get; set; }
+ public string? AvisNummer { get; set; }
///
/// Gibt den Typ des Avis an.
///
///
- [JsonProperty(PropertyName = "avisTyp", Required = Required.Always)]
+ [JsonProperty(PropertyName = "avisTyp", Required = Required.Default)]
[JsonPropertyName("avisTyp")]
[ProtoMember(1001)]
- public AvisTyp AvisTyp { get; set; }
+ public AvisTyp? AvisTyp { get; set; }
///
/// Avispositionen
///
- [JsonProperty(PropertyName = "positionen", Required = Required.Always)]
+ [JsonProperty(PropertyName = "positionen", Required = Required.Default)]
[JsonPropertyName("positionen")]
[NonOfficial(NonOfficialCategory.MISSING)]
[ProtoMember(1002)]
[BoKey]
- public List Positionen { get; set; }
+ public List? Positionen { get; set; }
///
/// Summenbetrag
///
- [JsonProperty(PropertyName = "zuZahlen", Required = Required.Always)]
+ [JsonProperty(PropertyName = "zuZahlen", Required = Required.Default)]
[JsonPropertyName("zuZahlen")]
[NonOfficial(NonOfficialCategory.MISSING)]
[ProtoMember(1003)]
- public Betrag ZuZahlen { get; set; }
-}
\ No newline at end of file
+ public Betrag? ZuZahlen { get; set; }
+}
diff --git a/BO4E/BO/BusinessObject.cs b/BO4E/BO/BusinessObject.cs
index 9b7b3988..e837dc06 100644
--- a/BO4E/BO/BusinessObject.cs
+++ b/BO4E/BO/BusinessObject.cs
@@ -301,8 +301,11 @@ public JSchema GetJsonScheme()
public static JSchema GetJsonSchema(Type boType)
{
if (!boType.IsSubclassOf(typeof(BusinessObject)))
+ {
throw new ArgumentException(
$"You must only request JSON schemes for Business Objects. {boType} is not a valid Business Object type.");
+ }
+
var generator = new JSchemaGenerator();
generator.GenerationProviders.Add(new StringEnumGenerationProvider());
var schema = generator.Generate(boType);
@@ -415,16 +418,24 @@ public static Dictionary GetExpandableFieldNames(string boTypeName
protected static Dictionary GetExpandablePropertyNames(Type type, bool rootLevel = true)
{
if (rootLevel && !type.IsSubclassOf(typeof(BusinessObject)))
+ {
throw new ArgumentException("Only allowed for BusinessObjects");
+ }
+
var result = new Dictionary();
foreach (var prop in type.GetProperties())
{
string fieldName;
var jpa = prop.GetCustomAttribute();
if (jpa?.PropertyName != null)
+ {
fieldName = jpa.PropertyName;
+ }
else
+ {
fieldName = prop.Name;
+ }
+
if (prop.PropertyType.IsSubclassOf(typeof(BusinessObject)))
{
foreach (var subResult in GetExpandablePropertyNames(prop.PropertyType, false))
@@ -477,8 +488,11 @@ public Dictionary GetBoKeys()
public static List GetBoKeyProps(Type boType)
{
if (!boType.IsSubclassOf(typeof(BusinessObject)))
+ {
throw new ArgumentException(
$"Business Object keys are only defined on Business Object types but {boType} is not a Business Object.");
+ }
+
return boType.GetProperties()
.Where(p => p.GetCustomAttributes(typeof(BoKey), false).Length > 0)
.OrderBy(ap => ap.GetCustomAttribute()?.Order)
@@ -511,7 +525,10 @@ internal class BaseSpecifiedConcreteClassConverter : DefaultContractResolver
protected override JsonConverter ResolveContractConverter(Type objectType)
{
if (typeof(BusinessObject).IsAssignableFrom(objectType) && !objectType.IsAbstract)
+ {
return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
+ }
+
return base.ResolveContractConverter(objectType);
}
}
@@ -529,7 +546,11 @@ public override bool CanConvert(Type objectType)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
- if (reader.TokenType == JsonToken.Null) return null;
+ if (reader.TokenType == JsonToken.Null)
+ {
+ return null;
+ }
+
if (objectType.IsAbstract)
{
var jo = JObject.Load(reader);
@@ -567,12 +588,17 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
continue;
}
- if (boType != null) break;
+ if (boType != null)
+ {
+ break;
+ }
}
if (boType == null)
+ {
throw new NotImplementedException(
$"The type '{jo["boTyp"].Value()}' does not exist in the BO4E standard.");
+ }
}
var deserializationMethod = serializer.GetType() // https://stackoverflow.com/a/5218492/10009545
@@ -624,12 +650,19 @@ public override bool CanConvert(Type objectType)
public override BusinessObject Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
- if (reader.TokenType == JsonTokenType.Null) return null;
+ if (reader.TokenType == JsonTokenType.Null)
+ {
+ return null;
+ }
+
if (typeToConvert.IsAbstract)
{
var jdoc = JsonDocument.ParseValue(ref reader);
if (!jdoc.RootElement.TryGetProperty("BoTyp", out var boTypeProp))
+ {
boTypeProp = jdoc.RootElement.GetProperty("boTyp");
+ }
+
var boTypeString = boTypeProp.GetString();
#pragma warning disable CS0618 // Type or member is obsolete
var boType = BoMapper.GetTypeForBoName(boTypeString);
@@ -648,12 +681,17 @@ public override BusinessObject Read(ref Utf8JsonReader reader, Type typeToConver
continue;
}
- if (boType != null) break;
+ if (boType != null)
+ {
+ break;
+ }
}
if (boType == null)
+ {
throw new NotImplementedException(
$"The type '{boTypeString}' does not exist in the BO4E standard.");
+ }
}
return System.Text.Json.JsonSerializer.Deserialize(jdoc.RootElement.GetRawText(), boType, options)
diff --git a/BO4E/BO/Energiemenge.cs b/BO4E/BO/Energiemenge.cs
index 3949bf02..3e97c048 100644
--- a/BO4E/BO/Energiemenge.cs
+++ b/BO4E/BO/Energiemenge.cs
@@ -82,8 +82,11 @@ static Energiemenge()
{
if (em1.LokationsId != em2.LokationsId || em1.LokationsTyp != em2.LokationsTyp ||
em1.VersionStruktur != em2.VersionStruktur)
+ {
throw new InvalidOperationException(
$"You must not add the Energiemengen with different locations {em1.LokationsId} ({em1.LokationsTyp}) (v{em1.VersionStruktur}) vs. {em2.LokationsId} ({em2.LokationsTyp}) (v{em2.VersionStruktur})");
+ }
+
var result = new Energiemenge
{
LokationsId = em1.LokationsId,
@@ -105,7 +108,9 @@ static Energiemenge()
foreach (var kvp1 in em1.UserProperties) result.UserProperties.Add(kvp1.Key, kvp1.Value);
foreach (var kvp2 in em2.UserProperties)
if (!result.UserProperties.ContainsKey(kvp2.Key))
+ {
result.UserProperties.Add(kvp2.Key, kvp2.Value);
+ }
}
if (em1.Energieverbrauch == null || em1.Energieverbrauch.Count == 0)
diff --git a/BO4E/BO/Lokationszuordnung.cs b/BO4E/BO/Lokationszuordnung.cs
index af0e202e..17d48460 100644
--- a/BO4E/BO/Lokationszuordnung.cs
+++ b/BO4E/BO/Lokationszuordnung.cs
@@ -1,8 +1,6 @@
-using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using BO4E.COM;
-using BO4E.ENUM;
using BO4E.meta;
using Newtonsoft.Json;
using ProtoBuf;
diff --git a/BO4E/BO/Marktlokation.cs b/BO4E/BO/Marktlokation.cs
index 6af09851..717121ba 100644
--- a/BO4E/BO/Marktlokation.cs
+++ b/BO4E/BO/Marktlokation.cs
@@ -430,6 +430,20 @@ public class Marktlokation : BusinessObject
[JsonPropertyOrder(42)]
public string? LokationsbuendelObjektcode { get; set; }
+ ///
+ /// Enthält die ID der vorgelagerten Lokation. Kann IDs unterschiedlicher Lokationen enthalten, also zum Beispiel
+ /// einer Messlokation oder Netzlokation.
+ ///
+ [JsonProperty(
+ Required = Required.Default,
+ Order = 43,
+ PropertyName = "vorgelagerteLokationsId"
+ )]
+ [JsonPropertyName("vorgelagerteLokationsId")]
+ [ProtoMember(43)]
+ [JsonPropertyOrder(43)]
+ public string? VorgelagerteLokationsId { get; set; }
+
///
/// Test if a is a valid Marktlokations ID.
///
@@ -438,9 +452,15 @@ public class Marktlokation : BusinessObject
public static bool ValidateId(string id)
{
if (string.IsNullOrWhiteSpace(id))
+ {
return false;
+ }
+
if (!RegexValidate.IsMatch(id))
+ {
return false;
+ }
+
var expectedChecksum = GetChecksum(id);
var actualChecksum = id.Substring(10, 1);
return actualChecksum == expectedChecksum;
@@ -459,17 +479,26 @@ public static bool ValidateId(string id)
public static string GetChecksum(string input)
{
if (string.IsNullOrWhiteSpace(input))
+ {
throw new ArgumentException(
$"Input '{nameof(input)}' must not be empty but was '{input}'"
);
+ }
+
if (input.Length is < 10 or > 11)
+ {
throw new ArgumentException(
$"Input '{nameof(input)}' must be a string with length 10 (to generate the checksum) or 11 (to validate the checksum)."
);
+ }
+
if (!RegexNumericString.IsMatch(input))
+ {
throw new ArgumentException(
$"Input '{nameof(input)}' must be numeric was '{input}'"
);
+ }
+
var oddChecksum = 0;
var evenChecksum = 0;
@@ -478,9 +507,13 @@ public static string GetChecksum(string input)
{
var s = input.Substring(i - 1, 1);
if (i % 2 == 0)
+ {
evenChecksum += 2 * int.Parse(s);
+ }
else
+ {
oddChecksum += int.Parse(s);
+ }
}
var result = (10 - (evenChecksum + oddChecksum) % 10) % 10;
diff --git a/BO4E/BO/Messlokation.cs b/BO4E/BO/Messlokation.cs
index e01c2b0d..753c651b 100644
--- a/BO4E/BO/Messlokation.cs
+++ b/BO4E/BO/Messlokation.cs
@@ -282,6 +282,7 @@ public class Messlokation : BusinessObject
[NonOfficial(NonOfficialCategory.CUSTOMER_REQUIREMENTS)]
public List? Messprodukte { get; set; }
+
// ///
// /// Lokationszuordnung, um bspw. die zugehörigen Marktlokationen anzugeben
// ///
@@ -308,6 +309,20 @@ public class Messlokation : BusinessObject
[JsonPropertyOrder(32)]
public string? LokationsbuendelObjektcode { get; set; }
+ ///
+ /// Enthält die ID der vorgelagerten Lokation. Kann Ids unterschiedlicher Lokationen enthalten, also zum Beispiel
+ /// einer Messlokation oder Marktlokation.
+ ///
+ [JsonProperty(
+ Required = Required.Default,
+ Order = 33,
+ PropertyName = "vorgelagerteLokationsId"
+ )]
+ [JsonPropertyName("vorgelagerteLokationsId")]
+ [ProtoMember(1027)]
+ [JsonPropertyOrder(33)]
+ public string? VorgelagerteLokationsId { get; set; }
+
///
/// Test if a is a valid messlokations ID.
///
diff --git a/BO4E/BO/Netzlokation.cs b/BO4E/BO/Netzlokation.cs
index 9773cf67..7bedf332 100644
--- a/BO4E/BO/Netzlokation.cs
+++ b/BO4E/BO/Netzlokation.cs
@@ -144,4 +144,18 @@ public class Netzlokation : BusinessObject
[JsonPropertyOrder(20)]
[NonOfficial(NonOfficialCategory.CUSTOMER_REQUIREMENTS)]
public string? LokationsbuendelObjektcode { get; set; }
+
+ ///
+ /// Enthält die ID der vorgelagerten Lokation. Kann Ids unterschiedlicher Lokationen enthalten, also zum Beispiel
+ /// einer Messlokation oder Marktlokation.
+ ///
+ [JsonProperty(
+ Required = Required.Default,
+ Order = 21,
+ PropertyName = "vorgelagerteLokationsId"
+ )]
+ [JsonPropertyName("vorgelagerteLokationsId")]
+ [ProtoMember(15)]
+ [JsonPropertyOrder(21)]
+ public string? VorgelagerteLokationsId { get; set; }
}
diff --git a/BO4E/BO/Rechnung.cs b/BO4E/BO/Rechnung.cs
index 68e5bc57..001bbe86 100644
--- a/BO4E/BO/Rechnung.cs
+++ b/BO4E/BO/Rechnung.cs
@@ -43,8 +43,10 @@ public Rechnung(JObject sapPrintDocument) : this()
var infoToken = sapPrintDocument.SelectToken("erdk") ?? sapPrintDocument.SelectToken("ERDK");
var tErdzToken = sapPrintDocument.SelectToken("tErdz") ?? sapPrintDocument.SelectToken("T_ERDZ");
if (tErdzToken == null)
+ {
throw new ArgumentException(
"The SAP print document did not contain a 'tErdz' token. Did you serialize using the right naming convention?");
+ }
Rechnungsnummer = (infoToken["opbel"] ?? infoToken["OPBEL"]).Value();
Rechnungsdatum = new DateTimeOffset(TimeZoneInfo.ConvertTime(
@@ -79,7 +81,10 @@ public Rechnung(JObject sapPrintDocument) : this()
foreach (var jrp in tErdzToken)
{
var belzart = (jrp["belzart"] ?? jrp["BELZART"]).ToString();
- if (belzart == "IQUANT" || belzart == "ROUND" || belzart == "ROUNDO") continue;
+ if (belzart == "IQUANT" || belzart == "ROUND" || belzart == "ROUNDO")
+ {
+ continue;
+ }
var rp = new Rechnungsposition();
decimal zeitbezogeneMengeWert = 0;
@@ -139,30 +144,40 @@ public Rechnung(JObject sapPrintDocument) : this()
if (rp.Einzelpreis == null)
{
if ((jrp["preisbtr"] ?? jrp["PREISBTR"]) != null)
+ {
rp.Einzelpreis = new Preis
{
Wert = decimal.Parse((jrp["preisbtr"] ?? jrp["PREISBTR"]).ToString()),
Einheit = waehrungseinheit,
Bezugswert = mengeneinheit
};
+ }
else
+ {
rp.Einzelpreis = new Preis
{
Wert = 0,
Einheit = waehrungseinheit,
Bezugswert = mengeneinheit
};
+ }
}
rp.Positionsnummer = (jrp["belzeile"] ?? jrp["BELZEILE"]).Value();
if ((jrp["bis"] ?? jrp["BIS"]) != null && (jrp["bis"] ?? jrp["BIS"]).Value() != "0000-00-00")
+ {
rp.LieferungBis = new DateTimeOffset(TimeZoneInfo.ConvertTime(
(jrp["bis"] ?? jrp["BIS"]).Value(),
CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo, TimeZoneInfo.Utc));
+ }
+
if ((jrp["ab"] ?? jrp["AB"]) != null && (jrp["ab"] ?? jrp["AB"]).Value() != "0000-00-00")
+ {
rp.LieferungVon = new DateTimeOffset(TimeZoneInfo.ConvertTime(
(jrp["ab"] ?? jrp["AB"]).Value(),
CentralEuropeStandardTime.CentralEuropeStandardTimezoneInfo, TimeZoneInfo.Utc));
+ }
+
if ((jrp["vertrag"] ?? jrp["VERTRAG"]) != null)
{
#pragma warning disable CS0618 // Type or member is obsolete
@@ -171,11 +186,13 @@ public Rechnung(JObject sapPrintDocument) : this()
}
if ((jrp["iAbrmenge"] ?? jrp["I_ABRMENGE"]) != null)
+ {
rp.PositionsMenge = new Menge
{
Wert = (jrp["iAbrmenge"] ?? jrp["I_ABRMENGE"]).Value(),
Einheit = mengeneinheit
};
+ }
if ((jrp["nettobtr"] ?? jrp["NETTOBTR"]) != null)
{
@@ -204,11 +221,15 @@ public Rechnung(JObject sapPrintDocument) : this()
decimal steuerProzent;
if ((jrp["stprz"] ?? jrp["STPRZ"]) != null &&
!string.IsNullOrWhiteSpace((jrp["stprz"] ?? jrp["STPRZ"]).Value()))
+ {
steuerProzent =
decimal.Parse((jrp["stprz"] ?? jrp["STPRZ"]).Value().Replace(",", ".").Trim(),
CultureInfo.InvariantCulture);
+ }
else
+ {
steuerProzent = steuerbetrag.Steuerwert / steuerbetrag.Basiswert * 100.0M;
+ }
steuerbetrag.Steuerkennzeichen = (int)steuerProzent switch
{
@@ -221,8 +242,10 @@ public Rechnung(JObject sapPrintDocument) : this()
}
if ((jrp["nettobtr"] ?? jrp["NETTOBTR"]).Value() <= 0)
+ {
Vorausgezahlt = new Betrag
{ Waehrung = waehrungscode, Wert = (jrp["nettobtr"] ?? jrp["NETTOBTR"]).Value() };
+ }
}
rp.Zeiteinheit = mengeneinheit;
@@ -247,11 +270,15 @@ public Rechnung(JObject sapPrintDocument) : this()
decimal steuerProzent;
if ((jrp["stprz"] ?? jrp["STPRZ"]) != null &&
!string.IsNullOrWhiteSpace((jrp["stprz"] ?? jrp["STPRZ"]).Value()))
+ {
steuerProzent =
decimal.Parse((jrp["stprz"] ?? jrp["STPRZ"]).Value().Replace(",", ".").Trim(),
CultureInfo.InvariantCulture);
+ }
else
+ {
steuerProzent = Math.Round(steuerbetrag.Steuerwert / steuerbetrag.Basiswert * 100.0M);
+ }
steuerbetrag.Steuerkennzeichen = steuerProzent switch
{
diff --git a/BO4E/BO/TechnischeRessource.cs b/BO4E/BO/TechnischeRessource.cs
index cd1e62a1..42e7cd81 100644
--- a/BO4E/BO/TechnischeRessource.cs
+++ b/BO4E/BO/TechnischeRessource.cs
@@ -1,4 +1,3 @@
-using System.Collections.Generic;
using System.ComponentModel;
using System.Text.Json.Serialization;
using BO4E.COM;
@@ -239,4 +238,18 @@ public class TechnischeRessource : BusinessObject
[JsonPropertyOrder(24)]
[NonOfficial(NonOfficialCategory.CUSTOMER_REQUIREMENTS)]
public string? LokationsbuendelObjektcode { get; set; }
-}
\ No newline at end of file
+
+ ///
+ /// Enthält die ID der vorgelagerten Lokation. Kann Ids unterschiedlicher Lokationen enthalten, also zum Beispiel
+ /// einer Messlokation oder Marktlokation.
+ ///
+ [JsonProperty(
+ Required = Required.Default,
+ Order = 25,
+ PropertyName = "vorgelagerteLokationsId"
+ )]
+ [JsonPropertyName("vorgelagerteLokationsId")]
+ [ProtoMember(25)]
+ [JsonPropertyOrder(25)]
+ public string? VorgelagerteLokationsId { get; set; }
+}
diff --git a/BO4E/BO/Vertrag.cs b/BO4E/BO/Vertrag.cs
index fb56cb5d..26cdf40f 100644
--- a/BO4E/BO/Vertrag.cs
+++ b/BO4E/BO/Vertrag.cs
@@ -215,6 +215,7 @@ protected void OnDeserialized(StreamingContext context)
{
if ((Vertragsteile == null || Vertragsteile.Count == 0) && UserProperties != null &&
UserProperties.ContainsKey("lokationsId"))
+ {
Vertragsteile = new List
{
new Vertragsteil
@@ -224,6 +225,7 @@ protected void OnDeserialized(StreamingContext context)
Lokation = UserProperties["lokationsId"] as string
}
};
+ }
}
}
@@ -253,6 +255,7 @@ public override Vertrag Read(ref Utf8JsonReader reader, Type typeToConvert, Json
var v = JsonSerializer.Deserialize(ref reader, Vertrag.VertragsSerializerOptions);
if ((v.Vertragsteile == null || v.Vertragsteile.Count == 0) && v.UserProperties != null &&
v.UserProperties.ContainsKey("lokationsId"))
+ {
v.Vertragsteile = new List
{
new()
@@ -262,6 +265,8 @@ public override Vertrag Read(ref Utf8JsonReader reader, Type typeToConvert, Json
Lokation = ((JsonElement) v.UserProperties["lokationsId"]).GetString()
}
};
+ }
+
return v;
}
diff --git a/BO4E/BO4E.csproj b/BO4E/BO4E.csproj
index cf1739ab..a4860b0b 100644
--- a/BO4E/BO4E.csproj
+++ b/BO4E/BO4E.csproj
@@ -1,98 +1,98 @@
-
-
- netstandard2.0
- BO4E
- true
- Hochfrequenz.BO4Enet
- Hochfrequenz Untenehmensberatung GmbH
- BO4E .net core bindings
- https://github.com/Hochfrequenz/BO4E-dotnet/
-
- 0.2.50
- BO4Enet
- false
- true
-
-
- true
-
-
- $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- https://github.com/Hochfrequenz/BO4E-dotnet/
- false
- LICENSE.txt
-
- git
- true
- Embedded
- True
- latest
- BO4Enet.xml
- annotations
-
-
-
- false
- true
-
-
- DEBUG
- true
-
-
-
-
-
-
-
-
-
-
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Always
-
-
-
-
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
-
-
-
-
-
-
+
+
+ netstandard2.0
+ BO4E
+ true
+ Hochfrequenz.BO4Enet
+ Hochfrequenz Untenehmensberatung GmbH
+ BO4E .net core bindings
+ https://github.com/Hochfrequenz/BO4E-dotnet/
+
+ 0.2.50
+ BO4Enet
+ false
+ true
+
+
+ true
+
+
+ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ https://github.com/Hochfrequenz/BO4E-dotnet/
+ false
+ LICENSE.txt
+
+ git
+ true
+ Embedded
+ True
+ latest
+ BO4Enet.xml
+ annotations
+
+
+
+ false
+ true
+
+
+ DEBUG
+ true
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
diff --git a/BO4E/BoMapper.cs b/BO4E/BoMapper.cs
index 3cd264f1..12b21932 100644
--- a/BO4E/BoMapper.cs
+++ b/BO4E/BoMapper.cs
@@ -34,7 +34,10 @@ public static HashSet GetValidBoNames()
foreach (var t in types)
{
var m = BoRegex.Match(t.ToString());
- if (m.Success) result.Add(m.Groups["boName"].Value);
+ if (m.Success)
+ {
+ result.Add(m.Groups["boName"].Value);
+ }
}
return result;
@@ -55,7 +58,10 @@ public static HashSet GetValidBoNames()
///
public static Type GetTypeForBoName(string businessObjectName)
{
- if (businessObjectName == null) throw new ArgumentNullException(nameof(businessObjectName));
+ if (businessObjectName == null)
+ {
+ throw new ArgumentNullException(nameof(businessObjectName));
+ }
//Type[] types = Assembly.GetExecutingAssembly().GetTypes();
var clazz = Assembly.GetExecutingAssembly().GetType(PackagePrefix + "." + businessObjectName);
@@ -67,18 +73,4 @@ where string.Equals(boName, businessObjectName, StringComparison.CurrentCultureI
//throw new ArgumentException($"No implemented BusinessObject type matches the name '{businessObjectName}'.");
}
-
- ///
- /// Get JSON Scheme for given Business Object type
- ///
- /// Business Object type (e.g. typeof(BO4E.BO.Messlokation)
- /// A JSON scheme to be used for validation purposes.
- /// if given type is not derived from BusinessObject
- public static JSchema GetJsonSchemeFor(Type businessObjectType)
- {
- if (!businessObjectType.IsSubclassOf(typeof(BusinessObject)))
- throw new ArgumentException($"The given type {businessObjectType} is not derived from BusinessObject.");
- var bo = Activator.CreateInstance(businessObjectType) as BusinessObject;
- return bo.GetJsonScheme();
- }
}
diff --git a/BO4E/COM/Bankverbindung.cs b/BO4E/COM/Bankverbindung.cs
index 35aa17be..74bd89f1 100644
--- a/BO4E/COM/Bankverbindung.cs
+++ b/BO4E/COM/Bankverbindung.cs
@@ -1,5 +1,4 @@
using System.Text.Json.Serialization;
-using BO4E.ENUM;
using BO4E.meta;
using Newtonsoft.Json;
using ProtoBuf;
diff --git a/BO4E/COM/COM.cs b/BO4E/COM/COM.cs
index 4572cab9..2cfd5001 100644
--- a/BO4E/COM/COM.cs
+++ b/BO4E/COM/COM.cs
@@ -119,7 +119,11 @@ protected DateTime _TimeStamp
/// true
iff all elements of this COM and COM b are equal; false
otherwise
public bool Equals(COM b)
{
- if (b == null || b.GetType() != GetType()) return false;
+ if (b == null || b.GetType() != GetType())
+ {
+ return false;
+ }
+
return JsonConvert.SerializeObject(this) == JsonConvert.SerializeObject(b);
}
diff --git a/BO4E/COM/ExterneReferenz.cs b/BO4E/COM/ExterneReferenz.cs
index 9e7b2693..27ca31f0 100644
--- a/BO4E/COM/ExterneReferenz.cs
+++ b/BO4E/COM/ExterneReferenz.cs
@@ -62,7 +62,11 @@ internal static class ExterneReferenzExtensions
public static bool TryGetExterneReferenz(this ICollection? extReferences, string? extRefName,
out string? extRefWert)
{
- if (extRefName == null) throw new ArgumentNullException(nameof(extRefName));
+ if (extRefName == null)
+ {
+ throw new ArgumentNullException(nameof(extRefName));
+ }
+
if (extReferences == null)
{
extRefWert = null;
@@ -93,13 +97,21 @@ public static bool TryGetExterneReferenz(this ICollection? extR
public static List SetExterneReferenz(this List? extReferences,
ExterneReferenz extRef, bool overwriteExisting = false)
{
- if (extRef == null) throw new ArgumentNullException(nameof(extRef));
+ if (extRef == null)
+ {
+ throw new ArgumentNullException(nameof(extRef));
+ }
+
if (!extRef.IsValid())
+ {
throw new ArgumentException(
$"The external reference with {nameof(extRef.ExRefName)}='{extRef.ExRefName}' and {nameof(extRef.ExRefWert)}='{extRef.ExRefWert}' you tried to add is invalid.",
nameof(extRef));
- if (extReferences == null) return [extRef];
-
+ }
+ if (extReferences == null)
+ {
+ return new List { extRef };
+ }
if (extReferences.Any() && extReferences.TryGetExterneReferenz(extRef.ExRefName, out var existingRefWert))
{
if (overwriteExisting)
@@ -109,8 +121,10 @@ public static List SetExterneReferenz(this List(einheitString, true, out var einheit))
+ {
throw new ArgumentException($"'{einheitString}' is not a valid Mengeneinheit");
+ }
Einheit = einheit;
}
diff --git a/BO4E/UserPropertiesDataContractResolver.cs b/BO4E/UserPropertiesDataContractResolver.cs
index 07cbc032..2b2fb7c4 100644
--- a/BO4E/UserPropertiesDataContractResolver.cs
+++ b/BO4E/UserPropertiesDataContractResolver.cs
@@ -32,12 +32,23 @@ public UserPropertiesDataContractResolver(HashSet userPropertiesWhiteLis
public override JsonContract ResolveContract(Type type)
{
var contract = base.ResolveContract(type);
- if (!(contract is JsonObjectContract objContract)) return contract;
- if (objContract.ExtensionDataSetter == null) return contract;
+ if (!(contract is JsonObjectContract objContract))
+ {
+ return contract;
+ }
+
+ if (objContract.ExtensionDataSetter == null)
+ {
+ return contract;
+ }
+
var oldSetter = objContract.ExtensionDataSetter;
objContract.ExtensionDataSetter = (o, key, value) =>
{
- if (_allowList.Contains(key)) oldSetter(o, key, value);
+ if (_allowList.Contains(key))
+ {
+ oldSetter(o, key, value);
+ }
};
return contract;
}
diff --git a/BO4E/UserPropertiesExtensions.cs b/BO4E/UserPropertiesExtensions.cs
index 5a0c98ac..23bc78cc 100644
--- a/BO4E/UserPropertiesExtensions.cs
+++ b/BO4E/UserPropertiesExtensions.cs
@@ -34,7 +34,11 @@ public static bool TryGetUserProperty(this TParent paren
out TUserProperty value) where TParent : IUserProperties
{
var up = parent.UserProperties;
- if (string.IsNullOrWhiteSpace(userPropertyKey)) throw new ArgumentNullException(nameof(userPropertyKey));
+ if (string.IsNullOrWhiteSpace(userPropertyKey))
+ {
+ throw new ArgumentNullException(nameof(userPropertyKey));
+ }
+
if (up != null && up.TryGetValue(userPropertyKey, out var upToken))
{
switch (upToken)
@@ -106,7 +110,9 @@ public static TUserProperty GetUserProperty(this TParent
TUserProperty defaultValue) where TParent : IUserProperties
{
if (parent != null && parent.TryGetUserProperty(userPropertyKey, out TUserProperty actualValue))
+ {
return actualValue;
+ }
return defaultValue;
}
@@ -128,9 +134,16 @@ public static void SetUserProperty(this TParent parent,
TUserProperty value) where TParent : IUserProperties
{
// if user properties don't exist already, create them
- if (parent.UserProperties == null) parent.UserProperties = new Dictionary();
+ if (parent.UserProperties == null)
+ {
+ parent.UserProperties = new Dictionary();
+ }
+
// if there is already an value for the property, delete ist first
- if (parent.UserProperties.ContainsKey(userPropertyKey)) parent.UserProperties.Remove(userPropertyKey);
+ if (parent.UserProperties.ContainsKey(userPropertyKey))
+ {
+ parent.UserProperties.Remove(userPropertyKey);
+ }
// set the value
parent.UserProperties.Add(userPropertyKey, value);
@@ -147,9 +160,16 @@ public static void RemoveUserProperty(this TParent parent, string userP
where TParent : IUserProperties
{
// if user properties don't exist we cannot remove anything
- if (parent.UserProperties == null) return;
+ if (parent.UserProperties == null)
+ {
+ return;
+ }
+
// if there is already an value for the property, delete it
- if (parent.UserProperties.ContainsKey(userPropertyKey)) parent.UserProperties.Remove(userPropertyKey);
+ if (parent.UserProperties.ContainsKey(userPropertyKey))
+ {
+ parent.UserProperties.Remove(userPropertyKey);
+ }
}
///
@@ -176,13 +196,19 @@ public static void RemoveUserProperty(this TParent parent, string userP
public static bool UserPropertyEquals(this TParent parent, string userPropertyKey,
TUserProperty other, bool ignoreWrongType = true) where TParent : IUserProperties
{
- if (parent.UserProperties == null) return false;
+ if (parent.UserProperties == null)
+ {
+ return false;
+ }
try
{
return parent.EvaluateUserProperty(userPropertyKey, value =>
{
- if (value == null && other != null) return false;
+ if (value == null && other != null)
+ {
+ return false;
+ }
return value == null || value.Equals(other);
}
@@ -210,7 +236,11 @@ public static TEvaluationResult EvaluateUserProperty(userPropertyKey, out var value)
? evaluation(value)
: default;
@@ -234,12 +264,18 @@ public static TEvaluationResult EvaluateUserProperty(this TParent parent, string flagKey, bool? flagValue = true)
where TParent : class, IUserProperties
{
- if (string.IsNullOrWhiteSpace(flagKey)) throw new ArgumentNullException(nameof(flagKey));
+ if (string.IsNullOrWhiteSpace(flagKey))
+ {
+ throw new ArgumentNullException(nameof(flagKey));
+ }
if (parent.UserProperties == null)
{
parent.UserProperties = new Dictionary();
- if (!flagValue.HasValue) return false;
+ if (!flagValue.HasValue)
+ {
+ return false;
+ }
}
else if (flagValue.HasValue && flagValue.Value == parent.HasFlagSet(flagKey))
{
@@ -248,7 +284,10 @@ public static bool SetFlag(this TParent parent, string flagKey, bool? f
if (!flagValue.HasValue)
{
- if (!parent.UserProperties.ContainsKey(flagKey)) return false;
+ if (!parent.UserProperties.ContainsKey(flagKey))
+ {
+ return false;
+ }
parent.UserProperties.Remove(flagKey);
return true;
@@ -285,7 +324,10 @@ public static bool SetFlag(this TParent parent, string flagKey, bool? f
public static bool HasFlagSet(this TParent parent, string flagKey)
where TParent : class, IUserProperties
{
- if (string.IsNullOrWhiteSpace(flagKey)) throw new ArgumentNullException(nameof(flagKey));
+ if (string.IsNullOrWhiteSpace(flagKey))
+ {
+ throw new ArgumentNullException(nameof(flagKey));
+ }
try
{
diff --git a/BO4E/meta/Bo4eUri.cs b/BO4E/meta/Bo4eUri.cs
index 4f4f9602..f373f714 100644
--- a/BO4E/meta/Bo4eUri.cs
+++ b/BO4E/meta/Bo4eUri.cs
@@ -34,14 +34,24 @@ public class Bo4eUri : Uri
/// URI string to be processed
public Bo4eUri(string uri) : base(uri)
{
- if (uri == null) throw new ArgumentNullException(nameof(uri), "URI string must not be null.");
+ if (uri == null)
+ {
+ throw new ArgumentNullException(nameof(uri), "URI string must not be null.");
+ }
+
/*if (!base.IsWellFormedOriginalString())
{
throw new ArgumentException($"The URI {uri} is not well formed.");
}*/
if (Scheme + "://" != Bo4EScheme)
+ {
throw new ArgumentException($"The scheme '{Scheme}' in {uri} is not valid. Expected '{Bo4EScheme}://'");
- if (GetBoName() == null) throw new ArgumentException($"There is no Business Object of type '{Host}'.");
+ }
+
+ if (GetBoName() == null)
+ {
+ throw new ArgumentException($"There is no Business Object of type '{Host}'.");
+ }
}
///
@@ -124,7 +134,11 @@ public static bool IsValid(string uri)
/// on the returned object.
public static Bo4eUri GetUri(BusinessObject bo, bool includeUserProperties = false)
{
- if (bo == null) throw new ArgumentNullException(nameof(bo), "Business Object must not be null.");
+ if (bo == null)
+ {
+ throw new ArgumentNullException(nameof(bo), "Business Object must not be null.");
+ }
+
var baseUriString = Bo4EScheme + bo.GetType().Name + "/";
var baseUri = new Bo4eUri(baseUriString);
var relativeUriBuilder = new StringBuilder();
@@ -136,9 +150,13 @@ public static Bo4eUri GetUri(BusinessObject bo, bool includeUserProperties = fal
if (keyProp.GetValue(bo) is string)
{
if (keyProp.GetValue(bo).ToString() == string.Empty)
+ {
relativeUriBuilder.Append(NullKeyPlaceholder + "/");
+ }
else
+ {
relativeUriBuilder.Append(keyProp.GetValue(bo) + "/");
+ }
}
else if (keyProp.GetValue(bo) is int)
{
@@ -188,7 +206,11 @@ public static Bo4eUri GetUri(BusinessObject bo, bool includeUserProperties = fal
private static IList GetKeyFields(BusinessObject bo)
{
- if (bo == null) throw new ArgumentNullException(nameof(bo), "Business Object must not be null.");
+ if (bo == null)
+ {
+ throw new ArgumentNullException(nameof(bo), "Business Object must not be null.");
+ }
+
return GetKeyProperties(bo.GetType());
}
@@ -199,8 +221,11 @@ private static IList GetKeyProperties(Type boType)
.OrderBy(af => af.GetCustomAttribute()?.Order)
.ToArray();
if (allKeyProperties.Length == 0)
+ {
throw new NotImplementedException(
$"Business Object {boType.Name} has no [BoKey] defined => can't create URI.");
+ }
+
IList ownKeyProps = new List();
var ignoreInheritedFields = false; // default
foreach (var keyProp in allKeyProperties)
@@ -211,7 +236,10 @@ private static IList GetKeyProperties(Type boType)
ownKeyProps.Add(keyProp);
}
- if (ignoreInheritedFields) return ownKeyProps;
+ if (ignoreInheritedFields)
+ {
+ return ownKeyProps;
+ }
return allKeyProperties.ToList();
}
@@ -236,7 +264,10 @@ public JObject GetQueryObject(Type boType = null, int i = 0)
// Method is called recursively if sub-BOs are part of the key. To distinguish between
// top level and recursive calls, check the value of boType and i.
if (boType == null) // top level call
+ {
boType = GetBoType();
+ }
+
result.Add("boTyp", boType.Name.ToUpper());
// The order of the FieldInfos is the same as the JsonProperty.Order attribute of the
@@ -247,7 +278,11 @@ public JObject GetQueryObject(Type boType = null, int i = 0)
{
var keyPropName = keyProp.Name;
var jpa = keyProp.GetCustomAttribute();
- if (jpa?.PropertyName != null) keyPropName = jpa.PropertyName;
+ if (jpa?.PropertyName != null)
+ {
+ keyPropName = jpa.PropertyName;
+ }
+
string keyValue;
try
{
@@ -258,7 +293,11 @@ public JObject GetQueryObject(Type boType = null, int i = 0)
break; // no arguments at all.
}
- if (keyValue.EndsWith("/")) keyValue = keyValue.Substring(0, keyValue.Length - 1);
+ if (keyValue.EndsWith("/"))
+ {
+ keyValue = keyValue.Substring(0, keyValue.Length - 1);
+ }
+
if (keyProp.PropertyType == typeof(string))
{
result.Add(keyPropName, keyValue == NullKeyPlaceholder ? null : keyValue);
@@ -272,10 +311,14 @@ public JObject GetQueryObject(Type boType = null, int i = 0)
}
else*/
if (int.TryParse(keyValue, out var keyValueInt))
+ {
result.Add(keyPropName, keyValueInt);
+ }
else
+ {
throw new ArgumentException(
$"Key segment {keyPropName} could not be parsed as int although an integer type was expected!");
+ }
}
else if (keyProp.PropertyType.IsSubclassOf(typeof(BusinessObject)))
{
@@ -297,7 +340,9 @@ public JObject GetQueryObject(Type boType = null, int i = 0)
var filter = query.Get("filter");
foreach (Match match in FilterAndPattern.Matches(filter))
if (boProps.Contains(match.Groups["key"].Value, StringComparer.OrdinalIgnoreCase))
+ {
result[match.Groups["key"].Value] = match.Groups["value"].Value;
+ }
}
return result;
@@ -316,7 +361,11 @@ public Bo4eUri AddFilter(IDictionary filterObject)
filterString = filterObject
.Where(kvp => kvp.Value != null && boFields.Contains(kvp.Key, StringComparer.OrdinalIgnoreCase))
.Aggregate(filterString, (current, kvp) => current + $"{andString}{kvp.Key} eq '{kvp.Value}'");
- if (filterString.StartsWith(andString)) filterString = filterString.Substring(andString.Length);
+ if (filterString.StartsWith(andString))
+ {
+ filterString = filterString.Substring(andString.Length);
+ }
+
query.Add("filter", filterString);
var ub = new UriBuilder(this)
{
@@ -341,7 +390,11 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT
///
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
- if (value is string @string) return new Bo4eUri(@string);
+ if (value is string @string)
+ {
+ return new Bo4eUri(@string);
+ }
+
return base.ConvertFrom(context, culture, value);
}
}
diff --git a/BO4E/meta/BusinessObjectSerializationBinder.cs b/BO4E/meta/BusinessObjectSerializationBinder.cs
index 59268034..22a81a61 100644
--- a/BO4E/meta/BusinessObjectSerializationBinder.cs
+++ b/BO4E/meta/BusinessObjectSerializationBinder.cs
@@ -27,13 +27,13 @@ static BusinessObjectSerializationBinder()
public static IList BusinessObjectAndCOMTypes { get; }
///
- public Type BindToType(string assemblyName, string typeName)
+ public Type BindToType(string? assemblyName, string typeName)
{
return BusinessObjectAndCOMTypes.SingleOrDefault(t => t.Name == typeName);
}
///
- public void BindToName(Type serializedType, out string assemblyName, out string typeName)
+ public void BindToName(Type serializedType, out string? assemblyName, out string typeName)
{
assemblyName = null;
typeName = serializedType.Name;
diff --git a/BO4E/meta/CentralEuropeStandardTime.cs b/BO4E/meta/CentralEuropeStandardTime.cs
index b98a01f0..f07c21ea 100644
--- a/BO4E/meta/CentralEuropeStandardTime.cs
+++ b/BO4E/meta/CentralEuropeStandardTime.cs
@@ -10,10 +10,15 @@ namespace BO4E.meta
///
public abstract class CentralEuropeStandardTime
{
+ private static readonly TimeZoneInfo? _CentralEuropeStandardTimezoneInfo;
+
///
/// Central Europe Standard Time as hard coded default time. Public to be used elsewhere ;)
///
- public static readonly TimeZoneInfo CentralEuropeStandardTimezoneInfo;
+ public static TimeZoneInfo CentralEuropeStandardTimezoneInfo
+ {
+ get => _CentralEuropeStandardTimezoneInfo!;
+ }
static CentralEuropeStandardTime()
{
@@ -22,14 +27,14 @@ static CentralEuropeStandardTime()
const string resourceFileName = "BO4E.meta.CentralEuropeStandardTime.json";
using var stream = assembly.GetManifestResourceStream(resourceFileName);
if (stream == null)
- // this should never ever happen
- throw new FileNotFoundException($"The file resource {resourceFileName} was not found.");
- using (var jsonReader = new StreamReader(stream))
+ // this should never ever happen
{
- var jsonString = jsonReader.ReadToEnd();
- //Console.WriteLine(jsonString);
- CentralEuropeStandardTimezoneInfo = JsonConvert.DeserializeObject(jsonString);
+ throw new FileNotFoundException($"The file resource {resourceFileName} was not found.");
}
+ using var jsonReader = new StreamReader(stream);
+ var jsonString = jsonReader.ReadToEnd();
+ //Console.WriteLine(jsonString);
+ _CentralEuropeStandardTimezoneInfo = JsonConvert.DeserializeObject(jsonString);
}
///
@@ -39,4 +44,4 @@ static CentralEuropeStandardTime()
// ReSharper disable once InconsistentNaming
public static TimeZoneInfo CENTRAL_EUROPE_STANDARD_TIME => CentralEuropeStandardTimezoneInfo;
}
-}
\ No newline at end of file
+}
diff --git a/BO4E/meta/DataCategoryAttribute.cs b/BO4E/meta/DataCategoryAttribute.cs
index 88c83e4f..b9f88cfb 100644
--- a/BO4E/meta/DataCategoryAttribute.cs
+++ b/BO4E/meta/DataCategoryAttribute.cs
@@ -30,7 +30,11 @@ public class DataCategoryAttribute : Attribute
///
public DataCategoryAttribute(params object[] enums)
{
- if (enums.Any(r => r.GetType().BaseType != typeof(Enum))) throw new ArgumentException("enums");
+ if (enums.Any(r => r.GetType().BaseType != typeof(Enum)))
+ {
+ throw new ArgumentException("enums");
+ }
+
Mapping = new HashSet();
foreach (Enum e in enums) Mapping.Add(e);
}
diff --git a/BO4E/meta/LenientConverters/LenientBo4eUriConverter.cs b/BO4E/meta/LenientConverters/LenientBo4eUriConverter.cs
index 767b2309..bd569d53 100644
--- a/BO4E/meta/LenientConverters/LenientBo4eUriConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientBo4eUriConverter.cs
@@ -22,9 +22,17 @@ public override bool CanConvert(Type objectType)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
- if (reader.Value == null) return null;
+ if (reader.Value == null)
+ {
+ return null;
+ }
+
var rawString = (string)reader.Value;
- if (rawString.Trim() == string.Empty) return null;
+ if (rawString.Trim() == string.Empty)
+ {
+ return null;
+ }
+
return new Bo4eUri(rawString);
}
diff --git a/BO4E/meta/LenientConverters/LenientDictionaryConverter.cs b/BO4E/meta/LenientConverters/LenientDictionaryConverter.cs
index a6cbd69e..25364910 100644
--- a/BO4E/meta/LenientConverters/LenientDictionaryConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientDictionaryConverter.cs
@@ -32,19 +32,29 @@ public override Dictionary Read(ref Utf8JsonReader reader, Type
JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
+ {
throw new JsonException($"JsonTokenType was of type {reader.TokenType}, only objects are supported");
+ }
var dictionary = new Dictionary();
while (reader.Read())
{
- if (reader.TokenType == JsonTokenType.EndObject) return dictionary;
+ if (reader.TokenType == JsonTokenType.EndObject)
+ {
+ return dictionary;
+ }
if (reader.TokenType != JsonTokenType.PropertyName)
+ {
throw new JsonException("JsonTokenType was not PropertyName");
+ }
var propertyName = reader.GetString();
- if (string.IsNullOrWhiteSpace(propertyName)) throw new JsonException("Failed to get property name");
+ if (string.IsNullOrWhiteSpace(propertyName))
+ {
+ throw new JsonException("Failed to get property name");
+ }
reader.Read();
@@ -72,7 +82,10 @@ public override void Write(Utf8JsonWriter writer, Dictionary val
private static void HandleValue(Utf8JsonWriter writer, string key, object objectValue)
{
- if (key != null) writer.WritePropertyName(key);
+ if (key != null)
+ {
+ writer.WritePropertyName(key);
+ }
switch (objectValue)
{
@@ -126,7 +139,11 @@ private object ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions opt
switch (reader.TokenType)
{
case JsonTokenType.String:
- if (reader.TryGetDateTime(out var date)) return date;
+ if (reader.TryGetDateTime(out var date))
+ {
+ return date;
+ }
+
return reader.GetString();
case JsonTokenType.False:
return false;
@@ -135,7 +152,11 @@ private object ExtractValue(ref Utf8JsonReader reader, JsonSerializerOptions opt
case JsonTokenType.Null:
return null;
case JsonTokenType.Number:
- if (reader.TryGetInt64(out var result)) return result;
+ if (reader.TryGetInt64(out var result))
+ {
+ return result;
+ }
+
return reader.GetDecimal();
case JsonTokenType.StartObject:
return Read(ref reader, null, options);
diff --git a/BO4E/meta/LenientConverters/LenientEnumListConverter.cs b/BO4E/meta/LenientConverters/LenientEnumListConverter.cs
index 136c7c3e..afea618d 100644
--- a/BO4E/meta/LenientConverters/LenientEnumListConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientEnumListConverter.cs
@@ -18,8 +18,16 @@ public class LenientEnumListConverter : JsonConverter
///
public override bool CanConvert(Type objectType)
{
- if (!objectType.IsGenericType) return false;
- if (objectType.GetGenericTypeDefinition() != typeof(List<>)) return false;
+ if (!objectType.IsGenericType)
+ {
+ return false;
+ }
+
+ if (objectType.GetGenericTypeDefinition() != typeof(List<>))
+ {
+ return false;
+ }
+
var expectedListElementType = objectType.GetGenericArguments()[0];
return expectedListElementType.ToString().StartsWith("BO4E.ENUM");
}
@@ -33,7 +41,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist
var expectedListElementType = objectType.GetGenericArguments()[0];
var expectedListType = typeof(List<>).MakeGenericType(expectedListElementType);
var result = Activator.CreateInstance(expectedListType);
- if (rawList == null || rawList.Count == 0) return result;
+ 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 is string && Enum.IsDefined(expectedListElementType, rawItem.ToString()))
diff --git a/BO4E/meta/LenientConverters/LenientJsonSerializerOptionsGenerator.cs b/BO4E/meta/LenientConverters/LenientJsonSerializerOptionsGenerator.cs
index 2fb3e8d1..125bd266 100644
--- a/BO4E/meta/LenientConverters/LenientJsonSerializerOptionsGenerator.cs
+++ b/BO4E/meta/LenientConverters/LenientJsonSerializerOptionsGenerator.cs
@@ -47,7 +47,8 @@ public static JsonSerializerOptions GetJsonSerializerOptions(this LenientParsing
foreach (LenientParsing lp in Enum.GetValues(typeof(LenientParsing)))
if (lenient.HasFlag(lp))
- // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
+ // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
+ {
switch (lp)
{
case LenientParsing.DATE_TIME:
@@ -85,6 +86,7 @@ public static JsonSerializerOptions GetJsonSerializerOptions(this LenientParsing
// no default case because NONE and MOST_LENIENT do not come up with more converters
}
+ }
//IContractResolver contractResolver;
//if (userPropertiesWhiteList.Count > 0)
//{
diff --git a/BO4E/meta/LenientConverters/LenientJsonSerializerSettingsGenerator.cs b/BO4E/meta/LenientConverters/LenientJsonSerializerSettingsGenerator.cs
index cc6865fd..75b4a705 100644
--- a/BO4E/meta/LenientConverters/LenientJsonSerializerSettingsGenerator.cs
+++ b/BO4E/meta/LenientConverters/LenientJsonSerializerSettingsGenerator.cs
@@ -34,7 +34,8 @@ public static JsonSerializerSettings GetJsonSerializerSettings(this LenientParsi
var converters = new List();
foreach (LenientParsing lp in Enum.GetValues(typeof(LenientParsing)))
if (lenient.HasFlag(lp))
- // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
+ // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
+ {
switch (lp)
{
case LenientParsing.DATE_TIME:
@@ -60,6 +61,7 @@ public static JsonSerializerSettings GetJsonSerializerSettings(this LenientParsi
// no default case because NONE and MOST_LENIENT do not come up with more converters
}
+ }
IContractResolver contractResolver = userPropertiesWhiteList.Count > 0
? new UserPropertiesDataContractResolver(userPropertiesWhiteList)
diff --git a/BO4E/meta/LenientConverters/LenientStringToIntConverter.cs b/BO4E/meta/LenientConverters/LenientStringToIntConverter.cs
index 1a03df2f..2d7a0385 100644
--- a/BO4E/meta/LenientConverters/LenientStringToIntConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientStringToIntConverter.cs
@@ -24,11 +24,21 @@ public override bool CanConvert(Type objectType)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
- if (reader.Value == null) return null;
+ if (reader.Value == null)
+ {
+ return null;
+ }
+
var numeric = new string(reader.Value.ToString().Where(char.IsDigit).ToArray());
- if (int.TryParse(numeric, out var intValue)) return intValue;
+ if (int.TryParse(numeric, out var intValue))
+ {
+ return intValue;
+ }
- if (objectType == typeof(int?)) return null;
+ if (objectType == typeof(int?))
+ {
+ return null;
+ }
return 0;
}
diff --git a/BO4E/meta/LenientConverters/LenientSystemTextJsonEnumListConverter.cs b/BO4E/meta/LenientConverters/LenientSystemTextJsonEnumListConverter.cs
index c7c76c15..d25d70d9 100644
--- a/BO4E/meta/LenientConverters/LenientSystemTextJsonEnumListConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientSystemTextJsonEnumListConverter.cs
@@ -19,9 +19,15 @@ public class LenientSystemTextJsonEnumListConverter : JsonConverterFactory
///
public override bool CanConvert(Type typeToConvert)
{
- if (!typeToConvert.IsGenericType) return false;
+ if (!typeToConvert.IsGenericType)
+ {
+ return false;
+ }
- if (typeToConvert.GetGenericTypeDefinition() != typeof(List<>)) return false;
+ if (typeToConvert.GetGenericTypeDefinition() != typeof(List<>))
+ {
+ return false;
+ }
var expectedListElementType = typeToConvert.GetGenericArguments()[0];
return expectedListElementType.ToString().StartsWith("BO4E.ENUM");
@@ -55,9 +61,15 @@ public class LenientSystemTextJsonEnumListConverter : JsonConverter
///
public override bool CanConvert(Type objectType)
{
- if (!objectType.IsGenericType) return false;
+ if (!objectType.IsGenericType)
+ {
+ return false;
+ }
- if (objectType.GetGenericTypeDefinition() != typeof(List<>)) return false;
+ if (objectType.GetGenericTypeDefinition() != typeof(List<>))
+ {
+ return false;
+ }
var expectedListElementType = objectType.GetGenericArguments()[0];
return expectedListElementType.ToString().StartsWith("BO4E.ENUM");
@@ -75,7 +87,10 @@ public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerial
var expectedListElementType = typeToConvert.GetGenericArguments()[0];
var expectedListType = typeof(List<>).MakeGenericType(expectedListElementType);
var result = Activator.CreateInstance(expectedListType);
- if (rawList == null || rawList.Count == 0) return result as T;
+ if (rawList == null || rawList.Count == 0)
+ {
+ return result as T;
+ }
// First try to parse the List normally, in case it's formatted as expected
foreach (var rawItem in rawList)
diff --git a/BO4E/meta/LenientConverters/LenientSystemTextJsonStringToIntConverter.cs b/BO4E/meta/LenientConverters/LenientSystemTextJsonStringToIntConverter.cs
index bf0f2d90..db8f2408 100644
--- a/BO4E/meta/LenientConverters/LenientSystemTextJsonStringToIntConverter.cs
+++ b/BO4E/meta/LenientConverters/LenientSystemTextJsonStringToIntConverter.cs
@@ -31,7 +31,10 @@ public class LenientSystemTextJsonStringToIntConverter : JsonConverter
case JsonTokenType.String:
{
var numeric = new string(reader.GetString().Where(char.IsDigit).ToArray());
- if (int.TryParse(numeric, out var intValue)) return intValue;
+ if (int.TryParse(numeric, out var intValue))
+ {
+ return intValue;
+ }
break;
}
diff --git a/BO4E/meta/LenientConverters/NullableEnumConverter.cs b/BO4E/meta/LenientConverters/NullableEnumConverter.cs
index 9549053a..fcd7e2b7 100644
--- a/BO4E/meta/LenientConverters/NullableEnumConverter.cs
+++ b/BO4E/meta/LenientConverters/NullableEnumConverter.cs
@@ -17,7 +17,10 @@ public class StringNullableEnumConverter : JsonConverterFactory
public override bool CanConvert(Type typeToConvert)
{
if (Nullable.GetUnderlyingType(typeToConvert) == null)
+ {
return typeToConvert.ToString().StartsWith("BO4E.ENUM");
+ }
+
return Nullable.GetUnderlyingType(typeToConvert).ToString().StartsWith("BO4E.ENUM");
}
@@ -62,12 +65,17 @@ public StringNullableEnumConverter() : this(null)
public StringNullableEnumConverter(JsonSerializerOptions options)
{
// for performance, use the existing converter if available
- if (options != null) _converter = (JsonConverter)options.GetConverter(typeof(T));
+ if (options != null)
+ {
+ _converter = (JsonConverter)options.GetConverter(typeof(T));
+ }
// cache the underlying type
_underlyingType = Nullable.GetUnderlyingType(typeof(T));
if (_underlyingType == null)
+ {
_underlyingType = typeof(T);
+ }
}
///
@@ -96,13 +104,24 @@ public override bool CanConvert(Type typeToConvert)
public override T Read(ref Utf8JsonReader reader,
Type typeToConvert, JsonSerializerOptions options)
{
- if (_converter != null) return _converter.Read(ref reader, _underlyingType, options);
+ if (_converter != null)
+ {
+ return _converter.Read(ref reader, _underlyingType, options);
+ }
+
if (reader.TokenType == JsonTokenType.Null)
+ {
return default;
+ }
+
if (reader.TokenType == JsonTokenType.String)
{
var value = reader.GetString();
- if (string.IsNullOrEmpty(value)) return default;
+ if (string.IsNullOrEmpty(value))
+ {
+ return default;
+ }
+
// for performance, parse with ignoreCase:false first.
try
{
diff --git a/BO4E/meta/MultiLangResolver.cs b/BO4E/meta/MultiLangResolver.cs
index 9b811eda..ef17ea91 100644
--- a/BO4E/meta/MultiLangResolver.cs
+++ b/BO4E/meta/MultiLangResolver.cs
@@ -39,13 +39,17 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
// See if there is a [FieldName] attribute applied to the property
// for the requested language
- var att = prop.AttributeProvider.GetAttributes(true)
+ var att = prop.AttributeProvider?.GetAttributes(true)
.OfType()
.FirstOrDefault(a => a.Language == _language);
// if so, change the property name to the one from the attribute
- if (att != null) prop.PropertyName = att.Text;
+ if (att != null)
+ {
+ prop.PropertyName = att.Text;
+ }
+
return prop;
}
}
-}
\ No newline at end of file
+}
diff --git a/BO4E/meta/NonOfficialAttribute.cs b/BO4E/meta/NonOfficialAttribute.cs
index 2552dc30..2fbfe74d 100644
--- a/BO4E/meta/NonOfficialAttribute.cs
+++ b/BO4E/meta/NonOfficialAttribute.cs
@@ -31,8 +31,11 @@ public class NonOfficialAttribute : Attribute
public NonOfficialAttribute(params object[] enums)
{
if (enums.Any(r => r.GetType().BaseType != typeof(Enum) || r.GetType() != typeof(NonOfficialCategory)))
+ {
throw new ArgumentException($"You must only pass enums of type {nameof(NonOfficialCategory)}",
nameof(enums));
+ }
+
Mapping = new HashSet();
foreach (Enum e in enums) Mapping.Add(e);
}
diff --git a/BO4ETestProject/TestBO4E.csproj b/BO4ETestProject/TestBO4E.csproj
index 8941eee1..150d73c0 100644
--- a/BO4ETestProject/TestBO4E.csproj
+++ b/BO4ETestProject/TestBO4E.csproj
@@ -22,8 +22,9 @@
-
-
+
+
+
diff --git a/BO4ETestProject/TestBo4eUri.cs b/BO4ETestProject/TestBo4eUri.cs
index 75e22e36..2687b99f 100644
--- a/BO4ETestProject/TestBo4eUri.cs
+++ b/BO4ETestProject/TestBo4eUri.cs
@@ -85,7 +85,9 @@ public void TestUriConstructionAndKeyDeconstruction()
.Replace("\n", "")
.Replace("\r", "")
.Replace(" ", "") == "{\"vorname\":[null,null]}")
+ {
continue;
+ }
Assert.IsNull(patch, patch.ToString());
}
diff --git a/BO4ETestProject/TestBoMapperSystemText.cs b/BO4ETestProject/TestBoMapperSystemText.cs
index 2705abf6..41e818cc 100644
--- a/BO4ETestProject/TestBoMapperSystemText.cs
+++ b/BO4ETestProject/TestBoMapperSystemText.cs
@@ -37,16 +37,26 @@ public void TestBoMapping()
$"You have to specify the object name in test file {file}");
var lenients = LenientParsing.STRICT; // default
if (json.RootElement.TryGetProperty("lenientDateTime", out var boolElement) && boolElement.GetBoolean())
+ {
lenients |= LenientParsing.DATE_TIME;
+ }
if (json.RootElement.TryGetProperty("lenientEnumList", out var listElement) && listElement.GetBoolean())
+ {
lenients |= LenientParsing.ENUM_LIST;
+ }
if (json.RootElement.TryGetProperty("lenientBo4eUri", out var urlElement) && urlElement.GetBoolean())
+ {
lenients |= LenientParsing.BO4_E_URI;
+ }
if (json.RootElement.TryGetProperty("lenientStringToInt", out var intElement) &&
- intElement.GetBoolean()) lenients |= LenientParsing.STRING_TO_INT;
+ intElement.GetBoolean())
+ {
+ lenients |= LenientParsing.STRING_TO_INT;
+ }
+
BusinessObject bo = null;
try
{
@@ -61,7 +71,11 @@ public void TestBoMapping()
}
var regularOutputString = JsonSerializer.Serialize(bo, bo.GetType());
- if (bo.GetType() == typeof(Rechnung)) continue; // todo: fix this!
+ if (bo.GetType() == typeof(Rechnung))
+ {
+ continue; // todo: fix this!
+ }
+
/*if (json["input"]["boTyp"] != null)
{
//BusinessObject bo2 = BoMapper.MapObject((JObject)json["input"], lenients);
@@ -83,10 +97,16 @@ public void TestBoMapping()
}*/
HashSet whitelist;
if (json.RootElement.TryGetProperty("userPropWhiteList", out var whiteList))
+ {
whitelist = new HashSet(JsonSerializer.Deserialize>(whiteList.GetRawText()));
+ }
else
+ {
whitelist = new HashSet();
+ }
+
if (lenients == LenientParsing.STRICT)
+ {
foreach (LenientParsing lenient in Enum.GetValues(typeof(LenientParsing)))
{
// strict mappings must also work with lenient mapping
@@ -112,6 +132,7 @@ public void TestBoMapping()
// Assert.AreEqual(regularOutputString, dateLenietOutputString);
//}
}
+ }
}
}
@@ -260,9 +281,13 @@ public DateTime EventOccured
set
{
if (value == DateTime.MinValue)
+ {
eventOccured = new DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ }
else
+ {
eventOccured = value;
+ }
}
}
}
diff --git a/BO4ETestProject/TestHelper/JsonHelper.cs b/BO4ETestProject/TestHelper/JsonHelper.cs
index 02c7368d..0d87a605 100644
--- a/BO4ETestProject/TestHelper/JsonHelper.cs
+++ b/BO4ETestProject/TestHelper/JsonHelper.cs
@@ -13,8 +13,15 @@ public static JToken RemoveEmptyChildren(JToken token)
foreach (var prop in token.Children())
{
var child = prop.Value;
- if (child.HasValues) child = RemoveEmptyChildren(child);
- if (!IsEmpty(child)) copy.Add(prop.Name, child);
+ if (child.HasValues)
+ {
+ child = RemoveEmptyChildren(child);
+ }
+
+ if (!IsEmpty(child))
+ {
+ copy.Add(prop.Name, child);
+ }
}
return copy;
@@ -25,8 +32,15 @@ public static JToken RemoveEmptyChildren(JToken token)
foreach (var item in token.Children())
{
var child = item;
- if (child.HasValues) child = RemoveEmptyChildren(child);
- if (!IsEmpty(child)) copy.Add(child);
+ if (child.HasValues)
+ {
+ child = RemoveEmptyChildren(child);
+ }
+
+ if (!IsEmpty(child))
+ {
+ copy.Add(child);
+ }
}
return copy;
diff --git a/BO4ETestProject/TestJsonOrder.cs b/BO4ETestProject/TestJsonOrder.cs
index a5c91748..45ab713b 100644
--- a/BO4ETestProject/TestJsonOrder.cs
+++ b/BO4ETestProject/TestJsonOrder.cs
@@ -125,7 +125,10 @@ public void TestJsonOrderAttributesOfBO()
protected static void TestOrderFromAbstract(Type abstractBaseType)
{
if (!abstractBaseType.IsAbstract)
+ {
throw new ArgumentException($"The type {abstractBaseType} is not abstract", nameof(abstractBaseType));
+ }
+
var relevantTypes = typeof(BusinessObject).Assembly.GetTypes().Where(abstractBaseType.IsAssignableFrom);
foreach (var relevantType in relevantTypes.Where(t => !IgnoreOrderTypes.Contains(t) && !t.Name.Contains("Marktrolle")))
{
diff --git a/BO4ETestProject/TestNullable.cs b/BO4ETestProject/TestNullable.cs
index 7415cf13..fc8a30a7 100644
--- a/BO4ETestProject/TestNullable.cs
+++ b/BO4ETestProject/TestNullable.cs
@@ -34,7 +34,10 @@ public void TestNullableAttributesFromBO()
protected void TestNullableAttributesFromAbstract(Type abstractBaseType)
{
if (!abstractBaseType.IsAbstract)
+ {
throw new ArgumentException($"The type {abstractBaseType} is not abstract", nameof(abstractBaseType));
+ }
+
var relevantTypes = typeof(BusinessObject).Assembly.GetTypes()
.Where(t => abstractBaseType.IsAssignableFrom(t));
foreach (var relevantType in relevantTypes)
diff --git a/BO4ETestProject/TestProtobufAttributes.cs b/BO4ETestProject/TestProtobufAttributes.cs
index d6c2002f..dd2c7589 100644
--- a/BO4ETestProject/TestProtobufAttributes.cs
+++ b/BO4ETestProject/TestProtobufAttributes.cs
@@ -54,9 +54,12 @@ public void TestUniqueProtoIncludeTagsBO()
protected void TestUniqueProtobufMemberIdAbstract(Type abstractType)
{
if (!abstractType.IsAbstract)
+ {
throw new ArgumentException($"The type {abstractType} is not abstract", nameof(abstractType));
+ }
+
foreach (var type in
- typeof(BusinessObject).Assembly.GetTypes().Where(t => abstractType.IsAssignableFrom(t)))
+ typeof(BusinessObject).Assembly.GetTypes().Where(t => abstractType.IsAssignableFrom(t)))
TestProtobufType(type, type.BaseType == abstractType || type == abstractType);
}
@@ -99,9 +102,11 @@ protected void TestProtobufType(Type type, bool isDirectBase)
try
{
if (isDirectBase)
+ {
Assert.AreEqual(allFields.Length, fieldsWithProtoMemberAttribute.Count(),
$"Missing protobuf attributes for {type} for: " +
string.Join(", ", allFields.Except(fieldsWithProtoMemberAttribute)));
+ }
}
catch (ArgumentOutOfRangeException aoore) when (aoore.ParamName == "tag")
{
@@ -130,7 +135,10 @@ protected void TestProtobufType(Type type, bool isDirectBase)
protected void TestProtobufDateTimeWorkaround(Type abstractBaseType)
{
if (!abstractBaseType.IsAbstract)
+ {
throw new ArgumentException($"The type {abstractBaseType} is not abstract", nameof(abstractBaseType));
+ }
+
var relevantTypes = typeof(BusinessObject).Assembly.GetTypes()
.Where(t => abstractBaseType.IsAssignableFrom(t));
foreach (var relevantType in relevantTypes)
@@ -171,7 +179,10 @@ protected void TestProtobufDateTimeWorkaround(Type abstractBaseType)
protected void TestUniqueProtoIncludeTagAbstract(Type abstractBaseType) // ToDo: test this with preisblatt
{
if (!abstractBaseType.IsAbstract)
+ {
throw new ArgumentException($"The type {abstractBaseType} is not abstract", nameof(abstractBaseType));
+ }
+
var duplicateIncludeTags = typeof(BusinessObject).Assembly.GetTypes()
.Where(t => abstractBaseType.IsAssignableFrom(t))
.SelectMany(t => t.GetCustomAttributes(typeof(ProtoIncludeAttribute), false))
@@ -236,13 +247,18 @@ where baseType.IsAssignableFrom(inheritingType) && baseType != inheritingType
// Assert.IsTrue(typePair.baseType.GetCustomAttributes(typeof(ProtoContractAttribute), false).Any(), $"The (base) type {typePair.baseType} has not [ProtoContract] attribute."); // ToDo: re-add this line because fields on BO / COM level are not properly proto-serialized as of now!
if (typePair.inheritingType.BaseType ==
typeof(BusinessObject)) //because protobuf-net doesn't support mutliple levels of inheritance
+ {
Assert.IsTrue(
typePair.inheritingType.GetCustomAttributes(typeof(ProtoContractAttribute), false).Any(),
$"The (inheriting) type {typePair.inheritingType} has not [ProtoContract] attribute.");
+ }
else
+ {
Assert.IsFalse(
typePair.inheritingType.GetCustomAttributes(typeof(ProtoContractAttribute), false).Any(),
$"The (INDIRECTLY inheriting) type {typePair.inheritingType} has the [ProtoContract] attribute."); // bug in protobuf-net
+ }
+
if (typePair.inheritingType.BaseType == typePair.baseType &&
typePair.baseType != typeof(BusinessObject))
{
diff --git a/BO4ETestProject/TestZeitraumDeserialization.cs b/BO4ETestProject/TestZeitraumDeserialization.cs
index 47a7b9f4..0f2bba5c 100644
--- a/BO4ETestProject/TestZeitraumDeserialization.cs
+++ b/BO4ETestProject/TestZeitraumDeserialization.cs
@@ -2,9 +2,7 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
-using BO4E.BO;
using BO4E.COM;
-using BO4E.ENUM;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
diff --git a/TestBO4E.Extensions/TestBO4E.Extensions.csproj b/TestBO4E.Extensions/TestBO4E.Extensions.csproj
index f827d644..e4fb5671 100644
--- a/TestBO4E.Extensions/TestBO4E.Extensions.csproj
+++ b/TestBO4E.Extensions/TestBO4E.Extensions.csproj
@@ -19,8 +19,9 @@
-
-
+
+
+
diff --git a/TestBO4E.Extensions/TestEnergiemengeExtensionCompleteness.cs b/TestBO4E.Extensions/TestEnergiemengeExtensionCompleteness.cs
index e94e274a..d2236fc5 100644
--- a/TestBO4E.Extensions/TestEnergiemengeExtensionCompleteness.cs
+++ b/TestBO4E.Extensions/TestEnergiemengeExtensionCompleteness.cs
@@ -1,4 +1,3 @@
-using BO4E;
using BO4E.BO;
using BO4E.COM;
using BO4E.ENUM;
@@ -11,9 +10,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-
using System;
using System.Collections.Generic;
using System.IO;
@@ -146,7 +142,9 @@ internal void TestMonthlySlices(bool testFirstOnly = true, bool useParallelExecu
Assert.AreEqual(12,
result.Count); // don't care about values of coverage, just the start/end and count of reports generated.
if (testFirstOnly)
+ {
break; // one test is enough. the rest is covered by the individual completeness report tests
+ }
}
}
diff --git a/TestBO4E.Extensions/TestEnergiemengeExtensionPlausibility.cs b/TestBO4E.Extensions/TestEnergiemengeExtensionPlausibility.cs
index df3032a8..437880bc 100644
--- a/TestBO4E.Extensions/TestEnergiemengeExtensionPlausibility.cs
+++ b/TestBO4E.Extensions/TestEnergiemengeExtensionPlausibility.cs
@@ -27,7 +27,10 @@ public void TestPlausibilityReportGenerationSomeCustomer()
foreach (var key in new HashSet { "reference", "other", "expectedResult" })
if (!json.ContainsKey(key))
+ {
throw new ArgumentException($"Test file {boFile} has no key '{key}'.");
+ }
+
var emReference = JsonConvert.DeserializeObject(json["reference"].ToString());
var emOther = JsonConvert.DeserializeObject(json["other"].ToString());
diff --git a/TestBO4E.Extensions/TestMengeneinheitExtension.cs b/TestBO4E.Extensions/TestMengeneinheitExtension.cs
index 0c721ccd..e513d9b6 100644
--- a/TestBO4E.Extensions/TestMengeneinheitExtension.cs
+++ b/TestBO4E.Extensions/TestMengeneinheitExtension.cs
@@ -22,7 +22,11 @@ public void TestConversionFactor()
{
foreach (Mengeneinheit me in Enum.GetValues(typeof(Mengeneinheit)))
{
- if ((int)me == 0) continue;
+ if ((int)me == 0)
+ {
+ continue;
+ }
+
Assert.AreEqual(1.0M, me.GetConversionFactor(me));
Assert.IsTrue(me.IsConvertibleTo(me));
}
@@ -36,8 +40,10 @@ public void TestConversionFactor()
foreach (Mengeneinheit me1 in Enum.GetValues(typeof(Mengeneinheit)))
foreach (Mengeneinheit me2 in Enum.GetValues(typeof(Mengeneinheit)))
if (!me1.IsConvertibleTo(me2))
+ {
Assert.ThrowsException(() => me1.GetConversionFactor(me2),
$"Conversion {me1}-->{me2} should throw an exception!");
+ }
}
}
}
\ No newline at end of file
diff --git a/TestBO4E.Reporting/TestBO4E.Reporting.csproj b/TestBO4E.Reporting/TestBO4E.Reporting.csproj
index a6f263fa..f1ebc15a 100644
--- a/TestBO4E.Reporting/TestBO4E.Reporting.csproj
+++ b/TestBO4E.Reporting/TestBO4E.Reporting.csproj
@@ -15,8 +15,9 @@
-
-
+
+
+
diff --git a/TestBO4E.Reporting/TestReportToCsv.cs b/TestBO4E.Reporting/TestReportToCsv.cs
index d81557da..723f7c72 100644
--- a/TestBO4E.Reporting/TestReportToCsv.cs
+++ b/TestBO4E.Reporting/TestReportToCsv.cs
@@ -53,7 +53,10 @@ public void TestCompletenessReportToCsv()
var commaResult = cr.ToCsv(',', lineTerminator: Environment.NewLine, reihenfolge: reihenfolge);
var separator = "";
if (decimalSeparator == ",")
+ {
separator = "\"";
+ }
+
Assert.AreEqual(
$"DE12345,{separator}0" + decimalSeparator +
$"87{separator},2019-01-01T00:00:00Z,2019-03-01T00:00:00Z,", commaResult.Split(Environment.NewLine)[1]);